Angular中如何测试按钮点击事件?现有测试代码无法生效求修正
问题
我在component.html中有如下按钮:
<button type="button" class="btn" (click)="call()">Click me!!</button>
component.ts中的call方法如下:
call(): void { console.log('button clicked!!'); }
我尝试通过spyOn监听call方法,触发按钮点击来测试,但函数未被覆盖,测试代码如下:
it('onBtnClick_ShouldLogTheOutput', () => { // Arrange const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; fixture.detectChanges(); const spy = spyOn(app, 'call'); const btn = fixture.debugElement.query(By.css('.btn')); // Act btn.nativeElement.click(); fixture.detectChanges(); // Assert expect(spy).toHaveBeenCalled(); });
我还尝试了使用fakeAsync和tick,但依然无效。请问我哪里出错了?需要如何修正才能让测试生效?
原因分析
核心问题是**fixture.detectChanges()的调用时机错误**:
- 第一次
fixture.detectChanges()会触发组件初始化与模板绑定,此时模板里的(click)="call()"已经绑定了原始的call方法引用。 - 后续用
spyOn(app, 'call')替换组件实例上的方法时,模板绑定的还是旧的方法引用,所以点击按钮不会触发spy的调用。
修正方案
方案一:标准做法(推荐)
将spyOn的调用移到第一次fixture.detectChanges()之前,让模板绑定的是被spy替换后的方法:
it('onBtnClick_ShouldLogTheOutput', () => { // Arrange const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; // 先创建spy,再触发初始化和模板绑定 const spy = spyOn(app, 'call'); fixture.detectChanges(); const btn = fixture.debugElement.query(By.css('.btn')); // Act btn.nativeElement.click(); fixture.detectChanges(); // Assert expect(spy).toHaveBeenCalled(); });
方案二:手动重新绑定视图(特殊场景用)
如果必须在fixture.detectChanges()之后创建spy,可以手动重新绑定视图,让模板使用新的方法引用:
it('onBtnClick_ShouldLogTheOutput', () => { // Arrange const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; fixture.detectChanges(); const spy = spyOn(app, 'call'); // 重新绑定视图,更新模板的方法引用 fixture.componentRef.instance = app; fixture.detectChanges(); const btn = fixture.debugElement.query(By.css('.btn')); // Act btn.nativeElement.click(); fixture.detectChanges(); // Assert expect(spy).toHaveBeenCalled(); });
内容的提问来源于stack exchange,提问作者Prateek Patil
相关产品推荐
相关产品推荐

