Angular单元测试多ViewChild为空及CdkStepper步长为0如何解决
Angular CdkStepper向导组件单元测试问题解决方案
@ViewChild获取子组件实例为null的解决
- 确认
@ViewChild查询时机:默认@ViewChild在变更检测完成后才会赋值,如果子组件被*ngIf、cdk-step默认懒加载逻辑控制未渲染,初始化阶段查询就会返回null。Angular 8+默认static: false配置即可满足需求,不需要额外修改。 - 处理cdk-step懒加载逻辑:CdkStepper的
<cdk-step>默认是懒加载模式,只有当前激活的步骤才会渲染内嵌的子组件内容。所以测试时需要先切换到对应步骤,触发变更检测之后再查询子组件实例。 - 测试过程中每次修改步骤状态后,必须调用
fixture.detectChanges()触发视图更新,再做实例校验。
WizardComponent步长列表始终为0的解决
- 测试模块必须正确导入依赖:必须导入
CdkStepperModule,不能仅用CUSTOM_ELEMENTS_SCHEMA跳过组件校验,否则CdkStepper无法识别<cdk-step>节点,也就不会收集步长列表。 - 所有用到的组件必须在测试模块的
declarations中声明,包括WizardComponent、两个步骤子组件,避免组件解析失败。 - 步长列表收集时机:CdkStepper是在
ngAfterContentInit生命周期中收集内容投影的<cdk-step>节点,必须在第一次fixture.detectChanges()执行完成后再读取steps属性,否则会拿到空数组。
完整测试用例参考
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { CdkStepperModule } from '@angular/cdk/stepper'; import { AppComponent } from './app.component'; import { WizardComponent } from './wizard/wizard.component'; import { Wizard1Component } from './wizard-1/wizard-1.component'; import { Wizard2Component } from './wizard-2/wizard-2.component'; describe('AppComponent', () => { let component: AppComponent; let fixture: ComponentFixture<AppComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [CdkStepperModule], declarations: [ AppComponent, WizardComponent, Wizard1Component, Wizard2Component ] }).compileComponents(); fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should get all ViewChild instances and step list correctly', fakeAsync(() => { // 校验步长列表 expect(component.wizard.steps.length).toBe(2); // 切换到第一步,校验第一步实例 component.wizard.selectedIndex = 0; fixture.detectChanges(); tick(); expect(component.wizardStep1).toBeTruthy(); // 切换到第二步,校验第二步实例 component.wizard.selectedIndex = 1; fixture.detectChanges(); tick(); expect(component.wizardStep2).toBeTruthy(); })); });
如果不需要测试子组件内部逻辑,也可以创建selector和真实组件一致的mock子组件,声明到测试模块中即可正常被
@ViewChild查询到,减少测试依赖。
内容的提问来源于stack exchange,提问作者ddd
相关产品推荐
相关产品推荐

