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

Angular单元测试:Mock服务方法未生效无法读取属性报错

问题根因
  • Spy打桩时机晚于初始化逻辑执行
    你在第一个beforeEach中完成组件创建后立即执行了fixture.detectChanges(),Angular首次执行该方法时会自动触发组件的ngOnInit生命周期,此时fetchWeights方法已经运行。但你对weighInsService的Spy配置写在it测试用例内部,初始化执行时打桩逻辑还未生效,方法调用返回undefined,读取属性直接报错。
  • 缺失findLastWithField方法的打桩配置
    组件fetchWeights方法同时调用了findFirstWithField和findLastWithField两个方法,你只配置了前者的返回值,后者未打桩时默认返回undefined,读取current_weight属性也会触发相同报错。
  • TestBed配置缺失必要依赖
    组件构造函数注入了ModalController、CheckInsProvider,但测试模块的providers列表中没有提供这两个依赖,即便修复当前报错,后续也会触发注入失败问题。
修正后的测试代码
describe('ReEvaluationComponent', () => {
  let component: ReEvaluationComponent;
  let fixture: ComponentFixture<ReEvaluationComponent>;
  let mockGlobalsService = jasmine.createSpyObj('GlobalsService', ['base_url'])
  // 提前创建mock依赖
  let mockModalCtrl = jasmine.createSpyObj('ModalController', ['dismiss'])
  let mockCheckInsProvider = jasmine.createSpyObj('CheckInsProvider', [/* 填入组件用到的对应方法名 */])
  let mockWeighInsProvider = jasmine.createSpyObj('WeighInsProvider', ['findFirstWithField', 'findLastWithField'])
  let injector: TestBed;
  let weighInsService: any;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ReEvaluationComponent ],
      imports: [
        IonicModule.forRoot(),
        HttpClientTestingModule,
        RouterTestingModule,
      ],
      providers: [
        // 替换为mock依赖,避免真实服务的额外依赖影响测试
        {provide: WeighInsProvider, useValue: mockWeighInsProvider},
        {provide: ModalController, useValue: mockModalCtrl},
        {provide: CheckInsProvider, useValue: mockCheckInsProvider},
        {provide: GlobalsService, useValue: mockGlobalsService},
        {provide: PurchasesService, useValue: PurchasesServiceMock},
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(ReEvaluationComponent);
    component = fixture.componentInstance;
    // 删掉此处的detectChanges,放到it用例中打桩完成后再执行
  }));

  beforeEach(() => {
    injector = getTestBed()
    weighInsService = injector.get(WeighInsProvider)
  })

  it('should create', () => {
    // 先给两个调用的方法都配置返回值
    weighInsService.findFirstWithField.and.returnValue({
        current_weight: 200,
        visceral_fat: 20,
        body_fat: 20
    })
    weighInsService.findLastWithField.and.returnValue({
        current_weight: 180,
        visceral_fat: 15,
        body_fat: 18
    })
    // 打桩完成后再触发组件初始化
    fixture.detectChanges();
    expect(component).toBeTruthy();
  });
  // 其余测试用例遵循相同逻辑:先配置对应Spy的返回值,再调用detectChanges触发执行
})

内容的提问来源于stack exchange,提问作者Jeremy Thomas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:09:03