如果在其上下文中打开数据库之前已经存在一个数据库,则ProviderTestCase
和RenamingDelegatingContext
都将销毁该数据库,因此从这个意义上说,它们在打开SQLite数据库方面都有相同的低级方法.
您可以通过在setUp()
中打开装置中的数据库来利用这一点,这将确保您在每个测试用例之前使用新的数据库.
我建议您编写内容提供程序,而不是创建数据库适配器.您可以使用一个公共接口来访问数据,无论它是存储在数据库中还是网络上的某个地方,内容提供者的设计都可以方便地访问此类数据,但要付出一些IPC开销的代价,这是我们大多数人不应该关心的.
如果您这样做是为了访问SQLite数据库,那么框架将在单独的过程中为您完全管理数据库连接.作为补充,ProviderTestCase2<ContentProvider>
完全 bootstrap 了内容Provider 的测试上下文,而无需编写一行代码.
但是,这并不是说自己做 bootstrap 不是一项巨大的努力.因此,假设您有一个这样的数据库适配器;我们只关注open()
个用于获得对数据库的写访问权限的适配器,没什么特别的:
public class MyAdapter {
private static final String DATABASE_NAME = "my.db";
private static final String DATABASE_TABLE = "table";
private static final int DATABASE_VERSION = 1;
/**
* Database queries
*/
private static final String DATABASE_CREATE_STATEMENT = "some awesome create statement";
private final Context mCtx;
private SQLiteDatabase mDb;
private DatabaseHelper mDbHelper;
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE_STATEMENT);
}
@Override
public void onUpgrade(SQLiteDatabase db, int a, int b) {
// here to enable this code to compile
}
}
/**
* Constructor - takes the provided context to allow for the database to be
* opened/created.
*
* @param context the Context within which to work.
*/
public MyAdapter(Context context) {
mCtx = context;
}
/**
* Open the last.fm database. If it cannot be opened, try to create a new
* instance of the database. If it cannot be created, throw an exception to
* signal the failure.
*
* @return this (self reference, allowing this to be chained in an
* initialization call)
* @throws SQLException if the database could be neither opened or created
*/
public MyAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close() {
mDbHelper.close();
}
}
然后,您可以这样编写您的测试:
public final class MyAdapterTests extends AndroidTestCase {
private static final String TEST_FILE_PREFIX = "test_";
private MyAdapter mMyAdapter;
@Override
protected void setUp() throws Exception {
super.setUp();
RenamingDelegatingContext context
= new RenamingDelegatingContext(getContext(), TEST_FILE_PREFIX);
mMyAdapter = new MyAdapter(context);
mMyAdapter.open();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mMyAdapter.close();
mMyAdapter = null;
}
public void testPreConditions() {
assertNotNull(mMyAdapter);
}
}
因此,这里发生的情况是,一旦调用MyAdapter(context).open()
,RenamingDelegatingContext
的上下文实现将始终重新创建数据库.在调用MyAdapter.DATABASE_CREATE_STATEMENT
之后,您现在编写的每个测试都将与数据库的状态相冲突.