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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:18:44