You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 14:36:15