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

Jest模拟函数实例无法在模块间传递的问题排查与解决

问题分析与解决

为什么模拟函数没被调用?

核心原因是模块内部的函数引用和导出的函数引用脱节:
当你的模块(比如app.js)加载时,内部定义的sendToEH函数会被赋值给module.exports.sendToEH,但模块里的sendDataHandler直接引用的是内部的sendToEH变量,而不是exports.sendToEH。

你在测试中修改app.sendToEH = jest.fn(),只是替换了exports对象上的属性,但sendDataHandler调用的还是模块初始化时就绑定的原sendToEH函数,和你模拟的函数不是同一个引用。

至于第二个测试能通过,完全是因为你直接调用了app.sendToEH('asdf'),这个调用被模拟函数捕获到了,但sendDataHandler本身根本没调用这个模拟函数,属于假通过。

解决方法

根据你的代码结构,有几种可行的解决方案:

方案1:调整模块内部的调用方式

修改app.js里的sendDataHandler,让它调用导出的sendToEH,而不是直接引用内部变量:

// app.js
function sendToEH(data) {
  // 原实现逻辑
}

exports.sendToEH = sendToEH;

exports.sendDataHandler = async (req, res, next) => {
  // 改为调用exports上的sendToEH
  await exports.sendToEH(req.data);
};

这样修改后,你原来的测试代码就能正常工作,因为sendDataHandler会使用你替换后的模拟函数。

方案2:用Jest的jest.mock模拟整个依赖模块

如果sendToEH是抽离到单独的工具模块(比如eh-service.js),可以直接用jest.mock来模拟整个模块:
假设原代码结构:

// eh-service.js
module.exports = {
  sendToEH: (data) => {
    // 原实现
  }
};

// app.js
const { sendToEH } = require('./eh-service');

exports.sendDataHandler = async (req, res, next) => {
  await sendToEH(req.data);
};

测试代码:

// app.test.js
const app = require('./app');
const ehService = require('./eh-service');

// 模拟eh-service模块的sendToEH函数
jest.mock('./eh-service', () => ({
  sendToEH: jest.fn()
}));

test('sendDataHandler triggers sendToEH', async () => {
  const req = { data: 'test-data' };
  const res = {};
  const next = jest.fn();

  await app.sendDataHandler(req, res, next);

  expect(ehService.sendToEH).toHaveBeenCalledWith('test-data');
});

方案3:用jest.spyOn模拟实例/导出方法

如果你的app是类实例,或者sendDataHandler是通过this调用sendToEH的类方法,可以用jest.spyOn来替换目标方法:

// app.test.js
const app = require('./app');

test('sendDataHandler calls sendToEH', async () => {
  // 替换app上的sendToEH为模拟函数,并返回Promise
  const sendToEHSpy = jest.spyOn(app, 'sendToEH').mockResolvedValue();

  const req = { data: 'test' };
  const res = {};
  const next = jest.fn();

  await app.sendDataHandler(req, res, next);

  expect(sendToEHSpy).toHaveBeenCalledWith('test');
  // 测试后恢复原方法
  sendToEHSpy.mockRestore();
});

内容的提问来源于stack exchange,提问作者Daniel Gros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:53:12