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

Angular 11+Karma-Jasmine单元测试报错:Cannot read properties of undefined (reading 'filter')

Angular 11单元测试:TypeError: Cannot read properties of undefined (reading 'filter') 解决方法

问题场景

在使用Angular 11搭配Karma-Jasmine进行单元测试时,出现错误TypeError: Cannot read properties of undefined (reading 'filter'),排查后确认错误出现在组件ngOnInit调用的getserviceProvider函数中——对ServiceProvider执行filter方法时,ServiceProvider为undefined。尝试修复时曾导致所有测试用例失败。

相关代码片段

组件TS文件

ngOnInit(): void {
  this.getserviceProvider();
}
getserviceProvider() {
  this.Servicefile.getUpgWalletServiceProviders().subscribe(
    (data) => {
      this.UpgWalletServiceProviders = data?.body;
      this.ServiceProvider = data?.body;
      this.selectedDisplayName = this.ServiceProvider.filter((t: any) => t.isActive === true)[0].displayName;
    },
    (error) => {
      this.errorsService.handle(error);
    },
  );
}

单元测试文件

it('should create', () => {
  expect(component).toBeTruthy();
});

it('getMaxDigitalWalletsCount called successfully', fakeAsync(() => {
  spyOn(MockBusinessSettingsService, 'getMaxDigitalWalletsCount').and.callThrough();
  component.ngOnInit();
  expect(MockBusinessSettingsService.getMaxDigitalWalletsCount).toHaveBeenCalled();
  tick(100);
  expect(component.isLoadingResults).toBeFalse();
  fixture.detectChanges();
  expect(component.ChashInsForm.value).toEqual(
    jasmine.objectContaining({
      maxDigitalWalletsCount: listData.digitalWalletsCountUPG.body.maxDigitalWalletsCount,
    }),
  );
}));

问题分析

  1. 组件代码健壮性不足:虽然用data?.body赋值给ServiceProvider,但后续直接调用filter方法时未做判空处理。如果getUpgWalletServiceProviders返回的data.body为null/undefined,ServiceProvider就会是undefined,触发filter调用错误。
  2. 单元测试未Mock异步服务:测试中没有对Servicefile.getUpgWalletServiceProviders进行Mock,导致组件实际调用该方法时没有得到预期的返回值,ServiceProvider无法被正确赋值,进而引发错误。

修复步骤

1. 增强组件代码的健壮性

修改getserviceProvider函数,在调用filter前先判空,同时避免直接访问数组索引(防止数组为空时的越界错误):

getserviceProvider() {
  this.Servicefile.getUpgWalletServiceProviders().subscribe(
    (data) => {
      this.UpgWalletServiceProviders = data?.body;
      this.ServiceProvider = data?.body;
      // 先判断ServiceProvider是否存在且不为空数组
      if (this.ServiceProvider?.length) {
        const activeProvider = this.ServiceProvider.find(t => t.isActive === true);
        this.selectedDisplayName = activeProvider?.displayName || '';
      } else {
        this.selectedDisplayName = ''; // 或者设置业务需求的默认值
      }
    },
    (error) => {
      this.errorsService.handle(error);
    },
  );
}

2. 完善单元测试的Mock逻辑

在测试中MockServicefile.getUpgWalletServiceProviders方法,返回包含有效数据的Observable,确保组件能正确执行后续逻辑:

// 针对should create用例补充Mock逻辑
it('should create and initialize service providers', fakeAsync(() => {
  // 模拟服务返回的有效数据
  const mockProviders = [
    { isActive: true, displayName: 'Active Provider' },
    { isActive: false, displayName: 'Inactive Provider' }
  ];
  // Spy并返回模拟的Observable
  spyOn(MockServicefile, 'getUpgWalletServiceProviders').and.returnValue(of({ body: mockProviders }));
  
  component.ngOnInit();
  tick(); // 等待异步操作完成
  fixture.detectChanges();
  
  expect(component.ServiceProvider).toEqual(mockProviders);
  expect(component.selectedDisplayName).toBe('Active Provider');
  expect(component).toBeTruthy();
}));

// 完善原有的getMaxDigitalWalletsCount测试用例
it('getMaxDigitalWalletsCount called successfully', fakeAsync(() => {
  // 必须Mock getUpgWalletServiceProviders,避免组件报错
  spyOn(MockServicefile, 'getUpgWalletServiceProviders').and.returnValue(of({ body: [] }));
  spyOn(MockBusinessSettingsService, 'getMaxDigitalWalletsCount').and.callThrough();
  
  component.ngOnInit();
  tick(100);
  expect(MockBusinessSettingsService.getMaxDigitalWalletsCount).toHaveBeenCalled();
  expect(component.isLoadingResults).toBeFalse();
  fixture.detectChanges();
  expect(component.ChashInsForm.value).toEqual(
    jasmine.objectContaining({
      maxDigitalWalletsCount: listData.digitalWalletsCountUPG.body.maxDigitalWalletsCount,
    }),
  );
}));

关键注意点

  • 所有涉及异步服务调用的测试用例,都需要Mock对应的服务方法,返回可预测的Observable,避免依赖真实服务的响应。
  • 组件中对异步返回的数据处理必须添加判空逻辑,防止出现undefined/null调用方法的错误。

内容的提问来源于stack exchange,提问作者Nourhan Elsayed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:25:35