Angular 8测试:DevExtreme Grid子节点无法找到问题
解决Angular 8中DevExtreme Grid测试无法获取表格行的问题
我之前也碰到过一模一样的情况——明明Karma测试浏览器里表格已经正常渲染出数据行,但测试代码就是抓不到tr.dx-data-row节点。核心问题在于DevExtreme Grid是异步渲染组件,你的测试代码在组件还没完成数据加载和DOM渲染的异步流程时,就急着去查询元素了,自然拿不到结果。
下面是几个能解决这个问题的可行方案,你可以根据自己的测试场景选择:
方案1:用fakeAsync + tick模拟异步流程
Angular测试工具提供的fakeAsync和tick可以模拟时间流逝,等待所有异步任务完成后再执行断言:
import { fakeAsync, tick } from '@angular/core/testing'; // ... 其他测试代码保持不变 ... it('should render the table rows', fakeAsync(() => { // 触发数据加载操作 dxGrid.instance.getDataSource().load(); // tick()会等待所有异步操作完成 tick(); // 手动触发变化检测,确保DOM完成更新 fixture.detectChanges(); const rows = fixture.debugElement.queryAll(By.css('tr.dx-data-row')); expect(rows.length).toBe(mockData.length); }));
方案2:等待fixture.whenStable()完成
fixture.whenStable()会返回一个Promise,当组件所有异步操作(包括DevExtreme的数据加载和DOM渲染)都完成后才会resolve:
it('should render the table rows', async(() => { // 等待组件进入稳定状态 fixture.whenStable().then(() => { // 触发变化检测更新DOM fixture.detectChanges(); const rows = fixture.debugElement.queryAll(By.css('tr.dx-data-row')); expect(rows.length).toBe(mockData.length); }); }));
方案3:在beforeEach中异步预加载数据
你也可以把数据加载逻辑放到async修饰的beforeEach里,确保所有测试执行前,数据已经加载完成且DOM渲染完毕:
beforeEach(async(() => { component.data = mockData; fixture.detectChanges(); dxGridElement = fixture.debugElement.query(By.css('#grid')); dxGrid = <DxDataGridComponent>dxGridElement.componentInstance; dxGrid.instance.option('loadingTimeout', undefined); // 等待数据加载完成 await dxGrid.instance.getDataSource().load(); // 最后触发一次变化检测,保证DOM更新 fixture.detectChanges(); })); it('should render the table rows', () => { const rows = fixture.debugElement.queryAll(By.css('tr.dx-data-row')); expect(rows.length).toBe(mockData.length); });
需要额外注意:DevExtreme Grid的内部渲染逻辑完全是异步的,测试时必须等待这些异步流程全部结束,再去查询DOM元素,否则就会出现浏览器能看到但测试抓不到的情况。
内容的提问来源于stack exchange,提问作者Florian Ludewig
相关产品推荐
相关产品推荐

