gpt4 book ai didi

android - SQLite 数据库迁移似乎仅部分适用于 Espresso 测试

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:41:15 26 4
gpt4 key购买 nike

我们有一个 SQLite 数据库和一个相应的 SQLiteOpenHelper 子类。这个助手有一个 onDowngrade 实现,我想为其编写一个 Espresso 测试。

完整的onDowngrade 实现可用here .这是它的简化版本:

@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;");
}

该测试加载一个具有非常高版本号和添加或删除的列的数据库转储。然后它获得一个可读的数据库并确保版本已降级到当前预期的版本并且列名是预期的列名。完整的源代码可用here .这是它的样子:

@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));
}

如果我手动将相同的数据库转储加载到应用程序中,一切都会按预期进行。但是,当我运行此测试时,迁移中的最后一个 RENAME 似乎没有执行。如果我在迁移中注释掉最后两个 SQL 语句(删除原始表并将临时表重命名为原始表名),我可以断言临时表具有预期的内容(here 是一个提交,显示了这一点).

通过一些实验,我们发现在实例化 SQLiteOpenHelper 之后在测试中添加 databaseHelper.getReadableDatabase().close(); 可以使测试通过。鉴于 onDowngrade 调用包含在事务中,我不明白这是怎么可能的。

这是否表明我们的 onDowngrade 实现中存在错误?在 Espresso 测试中触发迁移在某些方面有所不同吗?

最佳答案

可能存在竞争条件,因为 SQLite 是共享资源。

例如。当测试在发出最后一个 COMMIT 语句之前运行时。

将其包装成 transaction (另见 Isolation In 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();

关于android - SQLite 数据库迁移似乎仅部分适用于 Espresso 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57280904/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com