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

如何使用ProxyRequire正确Mock Node.js测试中的RMQ实例依赖

首先说mock失效的核心原因:
你目前的写法有3个核心错误导致mock不生效:

  • proxyquire替换./a模块时的导出结构不匹配:原a.js导出的是{RMQ_INSTANCE: 实例对象},但你直接把fake实例赋值给了./a的导出,导致b.js里解构const { RMQ_INSTANCE } = require("./a")时拿到的是undefined,自然走了原有逻辑甚至报错。
  • 缺少完整的stub实现:你代码里的getFakeRMQStub没有定义,返回的假connection对象没有业务代码用到的createChannel、close方法,假channel对象也没有assertExchange、publish方法,调用时会直接报错。
  • 没有处理setTimeout的异步逻辑:测试执行完publishEmail就直接结束了,不会等500ms触发connection.close,也没法验证这部分逻辑。

以下是修正后的完整测试代码:

// filename: b.test.js
var proxyrequire = require("proxyquire").noCallThru();
var sinon = require("sinon");
const { assert } = require("sinon");

var producerTest = function () {
  it("producer connection - success test", async function () {
    // 1. 先构造所有依赖的stub
    const fakeChannelStub = {
      assertExchange: sinon.stub().resolves(),
      publish: sinon.stub().resolves()
    };
    const fakeConnectionStub = {
      createChannel: sinon.stub().resolves(fakeChannelStub),
      close: sinon.stub().resolves()
    };
    // 2. 构造假的RMQ实例,getInstance直接返回上面的假连接
    const fakeRMQInstance = {
      getInstance: sinon.stub().resolves(fakeConnectionStub)
    };
    // 3. proxyquire替换时要匹配原a.js的导出结构
    const rmqUtils = proxyrequire("../path/to/b.js", {
      "./a": {
        RMQ_INSTANCE: fakeRMQInstance
      }
    });
    // 4. 用sinon假时钟处理setTimeout,不需要真实等待500ms
    const clock = sinon.useFakeTimers();

    // 执行业务方法
    await rmqUtils.publishEmail("fake_msg");

    // 验证核心逻辑调用符合预期
    assert.calledOnce(fakeRMQInstance.getInstance);
    assert.calledOnce(fakeConnectionStub.createChannel);
    assert.calledWith(fakeChannelStub.assertExchange, "some_exchange", "topic", { durable: false });
    assert.calledWith(fakeChannelStub.publish, "some_exchange", "some_key", Buffer.from(JSON.stringify("fake_msg")));
    
    // 快进时间触发setTimeout回调
    clock.tick(500);
    assert.calledOnce(fakeConnectionStub.close);
    
    // 恢复时钟
    clock.restore();
  });
  afterEach(function () {
    sinon.verifyAndRestore();
  });
};
describe("test_producer", producerTest);

你也可以不用单独写fakeRMQClass,直接构造包含getInstance方法的对象即可,和上面的写法效果一致。

内容的提问来源于stack exchange,提问作者Abinash Biswal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:27:03