我正在为我使用 IndexedDb 的一些数据存储内容编写集成测试。这涉及通过创建数据库来设置每个测试,执行一些操作(运行测试),然后通过调用销毁每个测试database.close(),然后通过调用删除数据库window.indexedDB.deleteDatabase(DB_NAME)。
IDBDatabase.close()的文档指出“IDBDatabase 接口的 close() 方法立即返回并在单独的线程中 关闭连接。一旦数据库实际关闭,Close 不接受要触发的回调,因此无法确定连接是否已关闭。
我的初始测试是在尝试使用window.indexedDB.deleteDatabase(DB_NAME). 所有的测试都是打开数据库,除此之外没有执行任何操作。我能够通过在调用后添加一个小的超时来解决这个问题database.close()。
添加另一个向数据库添加数据的测试后,删除数据库的调用再次挂起,即使超时。数据确实被成功添加并且事务回调完成,所以我不确定为什么调用database.close()会挂起。任何见解将不胜感激。
编辑
我创建了一个项目来说明这个问题。代码可以在这里找到:https : //github.com/bgourlie/idb-hang-repro
需要注意的几件事——repro 是用 dart 编写的,因为我在那里看到了这个问题。该行为在 Chrome 和 Dartium(嵌入了 dart VM 的特殊版本的 Chromium)中都可以重现。对于那些没有使用过 Dart 但仍然想解决这个问题的人,请按照以下步骤操作:
{extracted_dir}/dart/dart-sdk/bin到 PATH。git clone https://github.com/bgourlie/idb-hang-repro.gitcd idb-hang-repropub getpub serve这将启动 pub 开发服务器,很可能在http://localhost:8080. 我已经在测试运行器中重现了这个问题,可以在http://localhost:8080/tests.html. 测试超时并显示任何输出需要很短的时间。还有一些重要的打印消息将显示在开发人员控制台上。
由于我一直在为我的 idb_shim 项目做大量的索引数据库实验,我可以分享我能够在新数据库上编写单元测试,只要我确保
据此,我能够修复您的测试项目(感谢分享),并进行了以下更改:
return tx.completed.then((_) {
print('transaction complete.');
},...
Run Code Online (Sandbox Code Playgroud)
作为旁注,我通常更喜欢删除 setUp 函数中的数据库,以便在先前的测试失败且数据库未清理时它可以正常工作。所以你现有代码的解决方案是:
setUp(() {
return dom.window.indexedDB.deleteDatabase(DB_NAME, onBlocked: (e) {
print('delete db blocked, but completing future anyway');
}).then((_) {
print('db successfully deleted!');
return dom.window.indexedDB.open(DB_NAME, version: 1, onUpgradeNeeded: (VersionChangeEvent e) {
print('db upgrade called (${e.oldVersion} -> ${e.newVersion})');
final db = (e.target as Request).result;
db.createObjectStore('foo', autoIncrement: true);
}, onBlocked: (e) => print('open blocked.')).then((_db_) {
print('db opened.');
db = _db_;
});
});
});
tearDown(() {
// note the 'close' here
db.close();
});
group('indexed DB delete hang repro', () {
test('second test which will add data', () {
print('adding data in second test...');
final tx = db.transaction('foo', 'readwrite');
final objectStore = tx.objectStore('foo');
objectStore.add({
'bar': 1,
'baz': 2
}).then((addedKey) {
print('object added to store with key=$addedKey');
}, onError: (e) => print('error adding object!'));
// note the 'return' here
return tx.completed.then((_) {
print('transaction complete.');
}, onError: (e) => print('transaction errored!'));
});
test('call setup and teardown', () {
print('just setup and teardown being called in first test.');
});
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1664 次 |
| 最近记录: |