Angular单元测试中EventEmitter未被调用问题排查
我来帮你搞定这个测试问题!你的功能在浏览器里正常运行,但测试失败的核心原因很明确——你在beforeEach中创建的emitActivateEditMode spy默认替换了原方法,没有执行真实的函数体,导致onActivateEditMode.emit()根本没被调用。
问题分析
看你在beforeEach里的这段代码:
spyOn(component, 'emitActivateEditMode');
默认情况下,spyOn会创建一个"空"的mock方法,它不会执行原函数里的this.onActivateEditMode.emit(flag)逻辑。所以不管你怎么触发按钮点击,emit方法都不会被调用,测试自然会报Number of calls: 0。
解决方案
这里有两种可行的修复方式,选一种适合你的即可:
方案1:让Spy执行真实方法
修改beforeEach里的spy,添加.callThrough(),这样当按钮点击触发emitActivateEditMode时,会执行原函数的逻辑,进而调用emit:
beforeEach(() => { fixture = TestBed.createComponent(MyComponent); component = fixture.componentInstance; // 添加.callThrough()让spy执行真实方法 spyOn(component, 'emitActivateEditMode').and.callThrough(); fixture.detectChanges(); });
方案2:移除不必要的Spy
如果你在测试用例里只关心onActivateEditMode.emit是否被正确调用,那beforeEach里的emitActivateEditMode spy完全是多余的,直接删掉它就行:
beforeEach(() => { fixture = TestBed.createComponent(MyComponent); component = fixture.componentInstance; // 移除这个不必要的spy // spyOn(component, 'emitActivateEditMode'); fixture.detectChanges(); });
额外小提示
在Angular测试中,使用triggerEventHandler触发事件有时候会比直接调用dispatchEvent或click()更贴合框架的事件处理逻辑,你可以试试这种写法:
import { By } from '@angular/platform-browser'; // ... const startEditProjectBtn = fixture.debugElement.query(By.css('[data-test-start-edit-project-btn]')); startEditProjectBtn.triggerEventHandler('click', null);
不过这不是必须的,只要修复了spy的问题,你的原有触发方式也能正常工作。
内容的提问来源于stack exchange,提问作者Jean D.
相关产品推荐
相关产品推荐

