Angular中如何测试组件实际渲染次数 解决查询为空报错问题
问题根源
- Router依赖覆盖时机错误:TestBed的Provider覆盖操作必须在调用
TestBed.configureTestingModule之后、createComponent之前完成,你在it块中二次覆盖Router时,TestBed已经完成了模块初始化,新的Provider值没有生效,导致模板中*ngIf="router.url == '/dostuff'"条件不成立,整个表单都未渲染,自然查不到子组件。 - CSS选择器用法错误:
document.getElementsByClassName接收的是纯类名,不能带前缀.;只有querySelector/By.css这类支持完整CSS规则的API才需要加类名前缀.。另外你模板里给app-sender加的类是class=".sender",多写了一个点,属于模板错误,需要先修正为class="sender"。 - 测试操作顺序错误:
TestBed.compileComponents()需要在模块配置完成后、创建组件实例前调用,你在创建组件后再调用完全没有作用。另外要确保组件的receivers属性已经被正确初始化赋值为长度3的数组。 - 不推荐直接用document查询DOM:Angular测试的组件渲染在fixture独立的DOM容器内,用
fixture.debugElement.queryAll查询更稳定,不会受其他测试用例的DOM污染。
修正代码
首先修正模板的类名错误:
<!-- 把类名前面的.去掉 --> <app-sender class="sender" [sender]="sender"></app-sender>
调整测试代码:
beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [WichtelnGroupComponent, SenderComponent, ReceiverComponent, WichtelnDetailsComponent, ConfirmationComponent, CheckConfirmationComponent], providers: [ WichtelDataHandlerService ], imports: [FormsModule] }) // 模块配置完成后统一编译组件,不要放在单条用例里 .compileComponents(); }); it('should render 3 app-receiver components when route is /dostuff', () => { // 1. 先覆盖Router取值,必须在createComponent之前操作 // 模板判断的是url == '/dostuff',直接mock对应路径即可,不需要带域名 TestBed.overrideProvider(Router, {useValue: {url: '/dostuff'}}); // 2. 创建组件实例 fixture = TestBed.createComponent(WichtelnGroupComponent); component = fixture.componentInstance; // 3. 如果组件的receivers没有自动初始化,手动赋值确保长度为3 // component.receivers = [{}, {}, {}]; // 4. 触发变更检测,让模板完成渲染 fixture.detectChanges(); // 断言逻辑 expect(component).toBeTruthy(); expect(component.receivers).toHaveSize(3); // 用Angular提供的API查询DOM更稳定 const senderEl = fixture.debugElement.query(By.css('app-sender.sender')); expect(senderEl).toBeTruthy(); const receiverEls = fixture.debugElement.queryAll(By.css('.wichteln-group-form .form-group-container app-receiver')); expect(receiverEls).toHaveSize(3); });
额外注意
如果组件的receivers是依赖服务返回的数据,需要提前mock对应服务的返回值,确保用例执行时receivers的长度确实为3。
内容的提问来源于stack exchange,提问作者Collin
相关产品推荐
相关产品推荐

