Angular Jasmine隔离测试:如何测试addListener内匿名函数
Angular单元测试覆盖addListener内部匿名函数的实现方案
问题原因
你当前的测试代码对toolsService.eventEmitter的mock存在缺陷:addListener被直接实现为空函数,没有保存组件注册进去的匿名回调,测试过程中这部分回调永远不会被执行,自然无法被覆盖率工具统计到。
具体实现步骤
1. 改造eventEmitter的mock逻辑
核心是把注册的事件回调缓存下来,提供手动触发事件的能力,方便测试时主动执行回调逻辑,同时修复原有mock的拼写错误:
// 缓存注册的事件回调 const registeredListeners: Record<string, Function> = {}; // 修复原mock拼写错误:componenntInstance → componentInstance let modalService = jasmine.createSpyObj("modalService", ["open"]); modalService.open.and.returnValue({ componentInstance: { showComponent: () => null, } }); let toolsService = jasmine.createSpyObj("toolsService", ["toRoute"], { eventEmitter: { addListener: (eventName: string, callback: Function) => { // 存下传入的匿名回调 registeredListeners[eventName] = callback; }, removeAllListeners: jasmine.createSpy("removeAllListeners"), // 新增触发事件的测试工具方法 triggerEvent: (eventName: string, payload?: unknown) => { registeredListeners[eventName]?.(payload); } } });
2. 编写测试用例覆盖两个监听回调
- 覆盖
close-modal事件回调
it("触发close-modal事件时,应调用removeAllListeners清理所有监听", () => { // 重置spy调用计数,避免前置逻辑干扰 (toolsService.eventEmitter.removeAllListeners as jasmine.Spy).calls.reset(); // 调用openModal完成事件注册 component.openModal("test-content-type"); // 手动触发close-modal事件,执行注册的匿名函数 toolsService.eventEmitter.triggerEvent("close-modal"); // 验证逻辑符合预期 expect(toolsService.eventEmitter.removeAllListeners).toHaveBeenCalled(); });
- 覆盖
contentEvent事件回调
it("触发contentEvent事件时,应调用setContent传入正确参数", () => { // 给组件的setContent方法打桩 spyOn(component, "setContent"); const testContentType = "mug-detail"; const testContent = { id: 123, name: "test mug" }; // 调用openModal完成事件注册 component.openModal(testContentType); // 触发contentEvent事件,传入测试参数 toolsService.eventEmitter.triggerEvent("contentEvent", testContent); // 验证参数传递和方法调用正确 expect(component.setContent).toHaveBeenCalledWith(testContentType, testContent); });
额外提示
ngOnInit里siteChange.subscribe注册的匿名函数可以用同样思路覆盖:把mock的basicService.siteChange替换为RxJS的Subject实例,测试时手动调用subject.next(testValue),即可触发回调执行,验证mugService.filterC.id赋值、mugService.getRelatedMugs调用的逻辑是否正确。
内容的提问来源于stack exchange,提问作者Ivan Martin Blanco
相关产品推荐
相关产品推荐

