Angular/Jasmine测试问题:无法选中并触发同class的第二个按钮
解决Angular中同class按钮的测试问题
首先咱们先拆解下你三个测试方案失败的核心原因:
方案1失败原因
- 第一个测试里你选择了
#save-lr-button,但这个按钮受*ngIf="rowDiff.count > 0"控制,默认情况下rowDiff.count应该是0,所以这个按钮根本没渲染,自然会出现Cannot read property 'nativeElement' of null的错误。 - 第二个测试完全搞反了按钮和方法的对应关系:你点击的是
#add-lr-button(绑定addLR()),却期望saveLR()被调用,这肯定不会成功。
方案2失败原因
你在beforeEach里提前获取了submitButtons,但此时第二个按钮因为*ngIf条件不满足还没渲染,所以submitButtons数组里只有第一个按钮。后续测试里按索引[1]或[0]点击,要么点到不存在的元素,要么点错了对应方法的按钮,导致断言失败。
方案3失败原因
第二个测试里用query(By.css('button.btn-primary'))只能获取到DOM中第一个匹配的按钮(也就是绑定addLR()的那个),所以点击后自然不会触发saveLR(),断言失败。
通用测试方案(不依赖id/name)
我们可以通过先控制*ngIf条件渲染目标按钮,再结合queryAll获取按钮列表并区分的方式来测试,具体代码如下:
测试addLR()方法
这个按钮始终存在,直接获取第一个匹配的按钮即可:
it(`should call addLR when the first primary button is clicked`, async(() => { spyOn(component, 'addLR'); // 获取所有.btn-primary按钮,第一个就是绑定addLR的按钮 const primaryButtons = de.queryAll(By.css('button.btn-primary')); primaryButtons[0].triggerEventHandler('click', null); // 推荐用triggerEventHandler替代nativeElement.click() fixture.detectChanges(); expect(component.addLR).toHaveBeenCalled(); }));
测试saveLR()方法
这个按钮需要先满足rowDiff.count > 0的条件才能渲染,所以步骤要多一步:
it(`should call saveLR when the second primary button is clicked`, async(() => { spyOn(component, 'saveLR'); // 1. 设置*ngIf条件为true,让按钮渲染 component.rowDiff = { count: 1 }; // 模拟rowDiff.count > 0的状态 fixture.detectChanges(); // 触发变更检测,渲染按钮 // 2. 获取所有.btn-primary按钮,此时数组里有两个元素,第二个就是绑定saveLR的按钮 const primaryButtons = de.queryAll(By.css('button.btn-primary')); primaryButtons[1].triggerEventHandler('click', null); fixture.detectChanges(); expect(component.saveLR).toHaveBeenCalled(); }));
额外优化点
- 用
triggerEventHandler('click', null)替代nativeElement.click(),这是Angular测试更推荐的方式,不需要依赖原生DOM元素的方法,更稳定。 - 每次修改组件状态后都要调用
fixture.detectChanges(),确保模板更新到最新状态。
内容的提问来源于stack exchange,提问作者SrAxi
相关产品推荐
相关产品推荐

