Angular单元测试:如何为AngularFire的delete()方法Mock创建SpyOn
Angular Firestore 删除函数测试问题解决
问题场景
服务中的删除函数代码:
deleteCharacter(id: string) { const characterCollectionRef = this.afs.collection<character>('users/' + this.authService.liveUid + '/Characters/'); return characterCollectionRef.doc(id).delete() }
测试时,注释掉Spy和断言语句能正常运行,但取消注释后会抛出错误 characterCollectionRef.doc is not a function,原测试代码如下:
it('deleteCharacter works', () => { AngularFirestoreMock.collection.and.returnValue({ doc: function () { return { delete: function () { return Promise.resolve() } } } }) // const spy = spyOn(AngularFirestoreMock.collection.doc, 'delete') service.deleteCharacter('id') // expect(spy).toHaveBeenCalled() });
问题原因
原Spy写法逻辑错误:AngularFirestoreMock.collection 是一个Spy函数,它本身不存在 doc 属性——只有当 collection 被调用后返回的对象才包含 doc 方法。直接尝试监听 AngularFirestoreMock.collection.doc 自然会找不到该方法,触发报错。
正确测试写法
方式1:拆分Spy并使用done回调处理异步
it('deleteCharacter works', (done) => { // 创建delete方法的Spy const deleteSpy = jasmine.createSpy('delete').and.returnValue(Promise.resolve()); // 创建doc方法的Spy,返回带有delete Spy的对象 const docSpy = jasmine.createSpy('doc').and.returnValue({ delete: deleteSpy }); // 让collection Spy返回带有doc Spy的对象 AngularFirestoreMock.collection.and.returnValue({ doc: docSpy }); // 调用服务方法,等待Promise完成后执行断言 service.deleteCharacter('id').then(() => { // 验证collection调用的路径参数正确 expect(AngularFirestoreMock.collection).toHaveBeenCalledWith('users/' + service.authService.liveUid + '/Characters/'); // 验证doc方法传入了目标id expect(docSpy).toHaveBeenCalledWith('id'); // 验证delete方法被触发 expect(deleteSpy).toHaveBeenCalled(); done(); }); });
方式2:用async/await简化异步测试流程
it('deleteCharacter works', async () => { const deleteSpy = jasmine.createSpy('delete').and.returnValue(Promise.resolve()); const docSpy = jasmine.createSpy('doc').and.returnValue({ delete: deleteSpy }); AngularFirestoreMock.collection.and.returnValue({ doc: docSpy }); // 等待异步删除操作完成 await service.deleteCharacter('id'); // 依次验证各方法的调用情况 expect(AngularFirestoreMock.collection).toHaveBeenCalledWith('users/' + service.authService.liveUid + '/Characters/'); expect(docSpy).toHaveBeenCalledWith('id'); expect(deleteSpy).toHaveBeenCalled(); });
内容的提问来源于stack exchange,提问作者Rusty Shackleford
相关产品推荐
相关产品推荐

