You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:53:17