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

Jasmine中如何对AngularFirestore嵌套函数的set方法使用spyOn

AngularFirestore Mock中监听set方法调用的实现方式

你当前的mock写法存在一个问题:每次调用collection()、doc()都会返回全新的匿名对象,测试逻辑中无法提前拿到set方法的引用挂载spy,推荐用以下两种方式实现监听:


方案1:提前声明可引用的mock对象(推荐)

在测试作用域提前把各层mock方法、spy对象声明为可访问的变量,在TestBed配置中直接复用这些变量,不需要每次调用都新建匿名对象:

describe('对应业务组件/服务的测试套件', () => {
  let mockSet: jasmine.Spy;

  beforeEach(() => {
    // 提前创建set方法的spy,默认返回resolve为void的Promise
    mockSet = jasmine.createSpy('set').and.resolveTo(void 0);

    TestBed.configureTestingModule({
      providers: [
        {
          provide: AngularFirestore,
          useValue: {
            collection: jasmine.createSpy('collection').and.returnValue({
              doc: jasmine.createSpy('doc').and.returnValue({
                set: mockSet
              })
            })
          }
        }
      ]
    });
  });

  it('验证set方法调用逻辑', async () => {
    // 执行业务逻辑,比如触发保存数据的操作
    await component.submitForm();
    fixture.detectChanges();

    // 直接断言spy的调用情况
    expect(mockSet).toHaveBeenCalledTimes(1);
    expect(mockSet).toHaveBeenCalledWith(/* 你期望传入set的入参 */);
  });
});

这种写法不受业务代码中传入的collection路径、doc id参数影响,spy稳定性最高。


方案2:动态获取引用挂载spy

如果不想修改现有mock结构,可以在测试用例执行前,从TestBed注入AngularFirestore实例,顺着调用链拿到set方法挂载spy:

it('动态挂载spy验证调用', () => {
  const afs = TestBed.inject(AngularFirestore);
  // 注意:此处collection、doc传入的参数需要和业务代码中调用时传的参数完全一致,否则spy不会生效
  const docRef = afs.collection('your-collection-path').doc('your-doc-id');
  spyOn(docRef, 'set').and.resolveTo(void 0);

  // 执行业务逻辑
  component.submitForm();

  // 断言调用
  expect(docRef.set).toHaveBeenCalled();
});

注意:这种写法依赖调用时的路径参数,如果业务代码中路径是动态生成的,很容易出现spy不触发的问题,仅适合路径固定的简单场景。


内容的提问来源于stack exchange,提问作者Joseph Zabinski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 16:33:25