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

Jest测试EventEmitter事件处理时sock.send调用次数为0如何解决

问题根因

测试失败的核心原因是测试用例中调用initializer.zmqSock()和initializer.wsClient()拿到的是全新实例,和app.js初始化时绑定逻辑的实例完全无关:

  • app.js在被require加载的阶段,就已经调用一次initializer.zmqSock()和initializer.wsClient()生成了内部使用的sock、ws实例,并且给该ws绑定了update事件监听
  • 测试用例中第二次调用两个方法返回的是新的EventEmitter和zmq实例,给新的ws emit事件无法触发app中绑定的监听逻辑,新sock的send方法自然不会被调用

最优实现方案

直接从mock函数的调用记录中取app初始化时生成的实例即可,不需要重新调用生成新实例:

const initializer = require("./dependencyInitializer");

jest.mock("./dependencyInitializer", () => {
    return {
        wsClient: jest.fn(() => {
            const EventEmitter = require("events")
            return new EventEmitter()
        }),
        zmqSock: jest.fn(() => {
            return {
                send: jest.fn()
            }
        })
    }
});
// mock完成后再引入app,保证app拿到的是mock后的实例
require("./app");

describe('on message received from websocket',() => {
    it('should pass it to zmq', () => {
        // 直接取app初始化时生成的实例,不需要重新调用方法
        const appWs = initializer.wsClient.mock.results[0].value;
        const appSock = initializer.zmqSock.mock.results[0].value;

        const testData = {topic: "test_topic", result: "ok"};
        // 给app实际绑定监听的ws实例emit事件
        appWs.emit("update", testData);

        // 支持同时校验调用次数和参数,逻辑更严谨
        expect(appSock.send).toHaveBeenCalledTimes(1);
        expect(appSock.send).toHaveBeenCalledWith([testData.topic, JSON.stringify(testData)]);
    });
});

额外优化建议

如果存在多个测试用例,可以在beforeEach中重置mock的调用记录,并且重新require app,避免用例之间的状态互相影响。

内容的提问来源于stack exchange,提问作者Luca Rosellini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:36:01