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
相关产品推荐
相关产品推荐

