Hél*_*tin 6 android sqliteopenhelper android-sqlite android-espresso
我们有一个SQLite数据库和一个对应的SQLiteOpenHelper子类。这个助手有一个onDowngrade我想为其编写Espresso测试的实现。
完整的onDowngrade实现在这里可用。这是它的简化版本:
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("CREATE TABLE IF NOT EXISTS foo_tmp (_id integer primary key, bar text not null, baz text not null);");
db.execSQL("INSERT INTO foo_tmp(_id,bar,baz) SELECT _id,bar,baz FROM foo;");
db.execSQL("DROP TABLE IF EXISTS foo;");
db.execSQL("RENAME TABLE foo_tmp TO foo;");
}
Run Code Online (Sandbox Code Playgroud)
该测试将加载具有很高版本号以及已添加或已删除列的数据库转储。然后,它将获得一个可读的数据库,并确保该版本已降级为当前的预期版本,并且列名是预期的列名。完整的资源在这里。看起来是这样的:
@Test
public void testMigration() throws IOException {
writeDatabaseFile("database" + File.separator + dbFilename);
InstancesDatabaseHelper databaseHelper = new InstancesDatabaseHelper();
SQLiteDatabase db = databaseHelper.getReadableDatabase();
assertThat(db.getVersion(), is(InstancesDatabaseHelper.DATABASE_VERSION));
List<String> newColumnNames = InstancesDatabaseHelper.getInstancesColumnNames(db);
assertThat(newColumnNames, contains(InstancesDatabaseHelper.CURRENT_VERSION_COLUMN_NAMES));
}
Run Code Online (Sandbox Code Playgroud)
如果我将相同的数据库转储手动加载到应用程序中,则一切都会按预期进行。但是,当我运行此测试时,看起来RENAME迁移中的最后一个未执行。如果我注释掉迁移中的最后两个SQL语句(删除原始表并将临时表重命名为原始表名),则可以断言临时表具有预期的内容(这是一个显示此内容的提交)。
通过一些实验,我们发现databaseHelper.getReadableDatabase().close();在实例化SQLiteOpenHelper使测试通过之后添加测试。鉴于该onDowngrade呼叫已封装在事务中,所以我不知道这是怎么可能的。
这是否表明我们的onDowngrade实现存在错误?在Espresso测试中触发迁移是否有所不同?
可能存在竞争条件,因为 SQLite 是共享资源。
例如。当测试在COMMIT发出最后一条语句之前运行时。
将其包装到事务中(另请参阅SQLite 中的隔离):
if(! BuildConfig.DEBUG) {
db.beginTransaction();
} else {
db.beginTransactionWithListener(new SQLiteTransactionListener() {
@Override public void onBegin() {Log.d(LOG_TAG, "onBegin()");}
@Override public void onCommit() {Log.d(LOG_TAG, "onCommit()");}
@Override public void onRollback() {Log.d(LOG_TAG, "onRollback()");}
});
}
try {
db.execSQL("CREATE TABLE IF NOT EXISTS foo_tmp (_id integer primary key, bar text not null, baz text not null);");
db.execSQL("INSERT INTO foo_tmp(_id,bar,baz) SELECT _id,bar,baz FROM foo;");
db.execSQL("DROP TABLE IF EXISTS foo;");
db.execSQL("RENAME TABLE foo_tmp TO foo;");
db.setTransactionSuccessful();
} catch(SQLException e){
Log.d(LOG_TAG, "" + e.getMessage());
} finally {
db.endTransaction();
}
db.close();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
89 次 |
| 最近记录: |