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

Jest用jest.fn()模拟模块方法测试失败,箭头函数模拟成功是什么原因?

核心原因

你遇到的问题本质是jest.mock的提升机制和ESM模块导入的执行顺序冲突导致的。

两种模拟方式的差异

  • 普通箭头函数模拟:仅模拟了method1的返回逻辑,没有额外的Jest mock能力(调用次数统计、参数校验、动态修改实现等)。因为工厂函数内部没有引用jest变量,不会受到jest.mock提升的影响,所以可以正常执行。
  • jest.fn模拟:返回的是Jest封装的模拟函数,具备完整的mock调试能力。但因为工厂函数内部引用了jest变量,当你使用ESM规范(即package.json中配置了"type": "module")运行测试时,jest.mock会被Jest提升到所有import语句之前执行,此时jest还未完成导入,工厂函数执行时访问jest会抛出未定义错误,最终导致模块模拟失败、测试不通过。
    如果是使用Babel转译ESM为CommonJS的场景,失败原因则是缺失__esModule标识,Jest会把模拟的模块当成CommonJS处理,导致命名导出解析异常。

解决方法

场景1:使用原生ESM运行测试

改用Jest针对ESM提供的jest.unstable_mockModule方法,配合动态导入实现模拟:

// App.test.js
import { jest } from '@jest/globals';

// 先声明模块模拟
jest.unstable_mockModule('./utils.js', () => ({
  method1: jest.fn().mockImplementation(() => "method1")
}));

// 再动态导入测试目标模块
const { showMsg } = await import('./App.js');

describe("test mock", () => {
  it("returns the correct value for Method 1", () => {
    expect(showMsg()).toBe("method1");
  });
});

场景2:使用Babel转译ESM为CommonJS运行测试

在jest.mock返回的模拟对象中添加__esModule: true标识即可:

jest.mock("./utils.js", () => ({ 
  __esModule: true,
  method1: jest.fn().mockImplementation(() => "method1"),
}));

内容的提问来源于stack exchange,提问作者rahul kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:24:07