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

如何修复Angular 7含Promise的ngOnInit测试中data未定义问题

解决Angular 7组件异步ngOnInit测试的undefined错误

问题根源

你的组件ngOnInit通过Promise.all读取Storage数据,再调用dataService.getAllData()(Observable)给this.data赋值,属于异步链式操作。测试时直接同步断言,会导致component.data还未被赋值就读取length,触发Cannot read properties of undefined (reading 'length')错误。

组件核心逻辑示例

ngOnInit() {
  Promise.all([
    this.storage.get('key1'),
    this.storage.get('key2')
  ]).then(([val1, val2]) => {
    this.dataService.getAllData(val1, val2).subscribe(data => {
      this.data = data;
    });
  });
}

解决方案:等待异步操作完成再断言

Angular测试提供两种常用异步处理方式,任选其一即可:

方式1:使用async + fixture.whenStable()

// 定义符合业务预期的模拟数据
const mockData = [{id:1}, {id:2}];

it('should assign data after ngOnInit completes', async () => {
  // Mock Storage.get返回已resolve的Promise
  spyOn(storage, 'get').and.returnValue(Promise.resolve('mock-value'));
  // Mock DataService.getAllData返回预期Observable
  spyOn(dataService, 'getAllData').and.returnValue(of(mockData));

  component.ngOnInit();
  await fixture.whenStable(); // 等待所有异步操作(Promise + Observable)完成
  fixture.detectChanges(); // 可选:若视图依赖data,触发变更检测更新视图

  // 先验证data存在,再校验length
  expect(component.data).toEqual(mockData);
  expect(component.data.length).toBe(mockData.length);
});

方式2:使用fakeAsync + tick()

import { fakeAsync, tick } from '@angular/core/testing';

const mockData = [{id:1}, {id:2}];

it('should assign data after ngOnInit completes', fakeAsync(() => {
  spyOn(storage, 'get').and.returnValue(Promise.resolve('mock-value'));
  spyOn(dataService, 'getAllData').and.returnValue(of(mockData));

  component.ngOnInit();
  tick(); // 模拟时间推进,直到所有异步任务执行完毕
  fixture.detectChanges();

  expect(component.data).toEqual(mockData);
  expect(component.data.length).toBe(mockData.length);
}));

关键注意事项

  1. 正确Mock依赖:必须确保storage.get返回已resolve的Promise,dataService.getAllData返回Observable(用of()创建),保证异步链能正常走到赋值逻辑。
  2. TestBed配置注入Mock实例:
beforeEach(() => {
  const mockStorage = jasmine.createSpyObj('Storage', ['get']);
  const mockDataService = jasmine.createSpyObj('DataService', ['getAllData']);

  TestBed.configureTestingModule({
    declarations: [YourComponent],
    providers: [
      { provide: Storage, useValue: mockStorage },
      { provide: DataService, useValue: mockDataService }
    ]
  });

  fixture = TestBed.createComponent(YourComponent);
  component = fixture.componentInstance;
  storage = TestBed.inject(Storage);
  dataService = TestBed.inject(DataService);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:10:29