Angular8:测试调用服务数组的函数问题排查
解决你的Angular测试问题:正确Mock属性而非方法
嘿,你的测试代码跑不起来主要是几个小细节没处理对,我帮你逐个梳理修正:
问题分析
你的待测试函数canShowIt里,this.requestsService.userProfil是一个数组属性,但测试代码犯了三个关键错误:
- 用了
spyOn()来Mock属性(这个API是专门用来Mock方法的) - 错误地返回了
Observable(of([{ id: 1 }])),但函数里直接用数组的some方法,根本不需要Observable - 对属性使用
toHaveBeenCalled()断言,这个断言只适用于方法调用,属性没法这么用
修正后的测试代码
这里给你两种可行的修正方案,按需选择:
方案1:直接给属性赋值(最简单,适用于public属性)
it('should return true when profile id matches', () => { // 获取service实例(Angular 9+推荐用inject代替get) const service = TestBed.inject(RequestService); // 直接给userProfil属性赋值为目标数组 service.userProfil = [{ id: 1 }]; // 必须设置component的profileDetail.id为匹配值,否则函数会返回false component.profileDetail = { id: 1 }; // 调用待测试函数 const result = component.canShowIt(); // 断言返回值正确 expect(result).toEqual(true); });
方案2:用spyOnProperty监听属性getter(适用于私有/带getter的属性)
如果userProfil是带getter的属性或者私有属性,用spyOnProperty来Mock更合适:
it('should return true when profile id matches', () => { const service = TestBed.inject(RequestService); // spyOnProperty监听属性的getter,返回目标数组 const userProfilSpy = spyOnProperty(service, 'userProfil').and.returnValue([{ id: 1 }]); component.profileDetail = { id: 1 }; const result = component.canShowIt(); expect(result).toEqual(true); // 如果要验证属性被访问,可以断言spy的调用次数 expect(userProfilSpy).toHaveBeenCalled(); });
额外注意点
- 一定要记得给
component.profileDetail.id设置匹配值,不然哪怕userProfil里有对应id,函数也会返回false - Angular 9及以上版本优先用
TestBed.inject()代替TestBed.get(),后者已经被官方废弃 - 别再对属性用
toHaveBeenCalled()啦,这个断言只针对方法调用,属性的验证可以用spy的调用次数或者直接断言属性值
内容的提问来源于stack exchange,提问作者Ami Ine
相关产品推荐
相关产品推荐

