使用 fake-indexeddb 可在 Node.js 中模拟 IndexedDB 进行单元测试,需安装并全局挂载 IDBFactory,注意异步操作、手动清理数据库及规避 Blob 支持等限制。

在 Node.js 环境中对使用 IndexedDB 的代码做单元测试,核心是用 fake-indexeddb 替换浏览器原生的 IndexedDB 实现。它实现了完整的 IndexedDB v2.0 API,能在 Node 里运行,配合 Jest 或其他测试框架非常方便。
安装 fake-indexeddb 和依赖
先安装必要包:
-
fake-indexeddb:提供 IndexedDB 的内存模拟实现 -
indexeddb-get-all-shim(可选):补全getAll()等较新方法(fake-indexeddb v4+ 已内置,但旧版需手动加) -
jest(或其他测试框架)
执行:
npm install --save-dev fake-indexeddb jest在测试前注入全局 indexedDB
Jest 默认不带全局 indexedDB,需在每个测试文件顶部或 setupFilesAfterEnv 中手动挂载:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const { IDBFactory } = require('fake-indexeddb');
global.indexedDB = new IDBFactory();
更稳妥的做法是在 Jest 配置中统一设置:
jest.config.jsmodule.exports = {
setupFilesAfterEnv: ['<rootDir>/test/setupIndexedDB.js'],
};
test/setupIndexedDB.js 内容:
const { IDBFactory } = require('fake-indexeddb');
global.indexedDB = new IDBFactory();
写测试时注意异步和数据库生命周期
IndexedDB 是事件驱动 + Promise 混合模型,测试中要正确 await 所有操作,尤其 open、add、get 等。fake-indexeddb 不会自动清库,每次测试后建议重置:
- 用
indexedDB.deleteDatabase(dbName)删除库(返回 Promise,需 await) - 或直接调用
IDBFactory.prototype.databases()获取当前所有 DB,批量清理(fake-indexeddb v5+ 支持)
推荐在 beforeEach 和 afterEach 中管理:
let db;
beforeEach(async () => {
const request = indexedDB.open('test-db', 1);
db = await new Promise((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
request.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains('users')) {
db.createObjectStore('users', { keyPath: 'id' });
}
};
});
});
afterEach(async () => {
await new Promise(resolve => indexedDB.deleteDatabase('test-db').onsuccess = resolve);
});
避免常见坑
- 不要在 test 文件外提前引用 indexedDB:Jest 模块缓存可能导致 setup 未生效就执行了被测代码
- fake-indexeddb 不支持 blob/file 类型键值:传入 Blob 会报错,测试中改用字符串或 number 模拟
-
事务自动提交:fake-indexeddb 的事务在事件循环结束时自动 commit,不用显式调
transaction.commit(),但也不支持手动 abort(除非用transaction.abort()显式触发) - 不支持多进程/跨 Worker 共享:纯内存实现,仅限单线程模拟

















