如何在Angular Jasmine测试中模拟History?解决空值读取报错
解决Angular Jasmine测试中History.state为null的报错问题
问题
编写Angular组件测试时出现报错:TypeError: Cannot read properties of null (reading 'data'),原因是组件在ngOnInit中直接访问history.state.data,但测试环境中history.state默认是null。
组件核心触发代码
create-organization.component.ts中引发错误的逻辑:
ngOnInit(): void { this.journeyService.clearData() const historyState = history.state.data ? history.state.data.data : null; if (historyState) { // 数据处理逻辑 } }
解决方案
方案1:给组件添加空值保护(推荐)
通过可选链操作符?.和空值合并运算符??增强代码健壮性,避免空指针错误:
ngOnInit(): void { this.journeyService.clearData() // 多层空值检查,防止history.state或其子属性为null时触发报错 const historyState = history.state?.data?.data ?? null; if (historyState) { const createOrganizationData: CreateOrganizationModel = { basic: historyState.data.basic, organizationalContact: historyState.data.organizationalContact, extraDetails: historyState.data.extraDetails, }; const journeyData = { ...createOrganizationData, isEdit: true }; this.journeyService.setData(journeyData); } }
方案2:在测试中模拟History.state
直接修改全局history对象,模拟所需的状态值:
模拟空状态(基础测试场景)
修改create-organization.component.spec.ts的beforeEach块:
beforeEach(async () => { // 模拟history.state为空对象,避免访问null的属性 Object.defineProperty(window.history, 'state', { value: {}, writable: true }); await TestBed.configureTestingModule({ imports: [RouterTestingModule], declarations: [CreateOrganizationComponent], providers: [ { provide: NavigationService, useValue: getNavigationServiceSpyObj() }, { provide: SpinnerService, useValue: getSpinnerServiceSpyObj() }, { provide: JourneyService, useValue: getJourneyServiceSpyObj() }, { provide: TerritoryService, useValue: getTerritoryServiceSpyObj() }, { provide: HttpClient, useValue: getHttpClientSpyObj() }, ], }).compileComponents(); fixture = TestBed.createComponent(CreateOrganizationComponent); component = fixture.componentInstance; fixture.detectChanges(); });
模拟带数据的状态(验证数据加载逻辑)
添加单独测试用例,模拟有业务数据的场景:
it('should load and process data from history state', () => { // 模拟包含业务数据的history.state结构 Object.defineProperty(window.history, 'state', { value: { data: { data: { basic: { orgName: 'Demo Organization' }, organizationalContact: { contactEmail: 'demo@org.com' }, extraDetails: { description: 'Test description' } } } }, writable: true }); // 重新触发组件初始化 fixture.detectChanges(); // 验证数据是否正确传递给journeyService const journeyService = TestBed.inject(JourneyService); expect(journeyService.setData).toHaveBeenCalledWith(jasmine.objectContaining({ isEdit: true, basic: { orgName: 'Demo Organization' } })); });
内容的提问来源于stack exchange,提问作者AmenNkala
相关产品推荐
相关产品推荐

