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
相关产品推荐
相关产品推荐

