如何为AngularJS+PouchDB代码库编写单元/集成测试及Karma数据库交互测试?
在Karma-Jasmine中测试AngularJS + PouchDB的数据库交互代码
我之前重构老AngularJS项目时碰到过完全一样的问题:过度依赖Protractor导致测试慢、不稳定,想把涉及DB的逻辑移到Karma里测试。这里给你几个经过实战验证的方案,分单元测试(隔离DB)和集成测试(轻量真实DB)两种方向:
方案1:用PouchDB内存适配器做集成测试
如果想测试真实的DB逻辑(比如数据存储、查询、同步的核心流程),但又不想用真实文件系统或远程DB,PouchDB的内存适配器是完美选择——它速度快,测试完自动销毁数据,不会污染环境。
步骤:
- 安装内存适配器依赖
npm install pouchdb-adapter-memory --save-dev
- 在Karma配置文件中引入PouchDB和内存适配器的脚本
在karma.conf.js的files数组里添加:
files: [ // 其他依赖... 'node_modules/pouchdb/dist/pouchdb.min.js', 'node_modules/pouchdb-adapter-memory/dist/pouchdb-adapter-memory.min.js' ]
- 测试中初始化/销毁内存DB
在测试套件里用beforeEach和afterEach来管理DB生命周期:
describe('PouchDB-backed Data Service', () => { let db; let dataService; beforeEach(inject((_dataService_) => { // 创建内存数据库 db = new PouchDB('test-db', { adapter: 'memory' }); // 把内存DB注入到你的服务中(假设你的服务依赖DB实例) dataService = _dataService_; dataService.setDB(db); })); afterEach(async () => { // 测试后销毁数据库 await db.destroy(); }); it('should save and retrieve a document correctly', async (done) => { const testDoc = { _id: 'test123', name: 'Test Item' }; // 调用服务的保存方法 await dataService.saveDoc(testDoc); // 获取保存的文档 const retrievedDoc = await dataService.getDoc('test123'); expect(retrievedDoc.name).toBe(testDoc.name); done(); }); });
方案2:用Jasmine Spy模拟PouchDB接口(单元测试)
如果只想测试业务逻辑,隔离数据库层,直接模拟PouchDB的方法会更高效,不用关心DB的具体实现。
实战示例:
假设你有一个封装了PouchDB的Angular服务dbService,里面有get、put方法:
describe('Business Logic Service', () => { let businessService; let mockDbService; beforeEach(() => { // 创建模拟的DB服务 mockDbService = jasmine.createSpyObj('dbService', ['put', 'get']); // 配置Angular模块,用模拟服务替换真实的dbService module('yourAppModule', ($provide) => { $provide.value('dbService', mockDbService); }); // 注入业务服务 inject((_businessService_) => { businessService = _businessService_; }); }); it('should process data before saving', () => { const rawData = { name: 'raw item' }; const expectedProcessedDoc = { _id: 'auto-gen-id', name: 'PROCESSED: raw item' }; // 让模拟的put方法返回成功promise mockDbService.put.and.returnValue(Promise.resolve({ ok: true })); // 调用业务服务的处理方法 businessService.processAndSave(rawData); // 断言put方法被调用,且传入了处理后的文档 expect(mockDbService.put).toHaveBeenCalledWith(jasmine.objectContaining({ name: 'PROCESSED: raw item' })); }); });
方案3:测试PouchDB同步逻辑(结合$httpBackend)
如果你的代码用到了PouchDB和远程CouchDB的同步功能,可以用AngularJS的$httpBackend拦截同步请求,返回模拟的响应,不用连接真实服务器:
describe('Sync Service', () => { let syncService; let $httpBackend; beforeEach(inject((_syncService_, _$httpBackend_) => { syncService = _syncService_; $httpBackend = _$httpBackend_; })); it('should handle successful sync', () => { // 拦截CouchDB的同步请求 $httpBackend.whenGET('/remote-couchdb/_changes') .respond(200, { results: [], last_seq: 1 }); // 触发同步 syncService.startSync(); // 刷新请求并断言逻辑 $httpBackend.flush(); expect(syncService.isSyncing()).toBe(false); }); });
额外实战技巧
- 处理异步代码:Karma-Jasmine支持
async/await或者done()回调,记得在异步测试里用这些方式等待promise完成 - 复用工具函数:把创建内存DB、模拟服务的逻辑抽成通用函数,减少测试代码重复
- 调试DB状态:测试中可以用
console.log(await db.allDocs())来查看内存DB的内容,方便排查问题
内容的提问来源于stack exchange,提问作者jkndrkn
相关产品推荐
相关产品推荐

