ES模块("type: module")项目中函数Mock的单元测试方案咨询
ES模块TypeScript项目的单元测试替代方案
我有一个在package.json中配置了"type": "module"的ES模块项目,实际用TypeScript开发,需要对模块内的部分函数进行单元测试。尝试用Jest的unstable_mockModule做Mock时,遇到了报错和类型错误的问题,而且手动实现完整Mock的工作量太大,无法接受。以下是几种可行的替代方案:
代码示例
待测试模块toto.js:
export function main() { const res = a(); return res; } export function a() { return 10; }
原测试文件test1.test.js的问题:
import { jest } from "@jest/globals"; jest.useFakeTimers(); // 报错 jest.unstable_mockModule("./toto", () => ({ ...import("./toto"), a: jest.fn(() => -2), })); // 类型错误:main is not a function jest.unstable_mockModule("./toto", () => { const totoModule = import("./toto"); return { ...totoModule, a: jest.fn(() => -2), }; });
方案一:转回CommonJS
- 移除
package.json中的"type": "module"字段,或者在tsconfig.json里把"module"配置为"CommonJS",让TypeScript编译输出CommonJS模块。 - 这样就能用Jest成熟稳定的
jest.mock语法来Mock,不用依赖不稳定的unstable_mockModule,示例如下:
// test1.test.js const { main } = require('./toto'); jest.mock('./toto', () => { // 保留原模块的其他导出,只Mocka函数 const originalModule = jest.requireActual('./toto'); return { ...originalModule, a: jest.fn(() => -2) }; }); test('main函数使用Mock后的a函数', () => { expect(main()).toBe(-2); });
- 缺点:如果项目大量依赖ES模块专属特性(比如顶级
await、ES模块路径解析),可能需要调整部分代码适配CommonJS。
方案二:改用Vitest作为测试框架
- Vitest原生支持ES模块,Mock语法和Jest高度兼容,不需要额外复杂配置就能直接Mock模块内函数,而且对TypeScript的支持开箱即用:
// test1.test.ts import { vi, expect, test } from 'vitest'; import { main } from './toto'; vi.mock('./toto', async () => { const originalModule = await import('./toto'); return { ...originalModule, a: vi.fn(() => -2) }; }); test('main返回Mock后的结果', () => { expect(main()).toBe(-2); });
- 优点:测试速度比Jest快,ES模块支持完善,TypeScript无需额外配置,Mock逻辑更直观。
方案三:使用Jasmine进行测试
- Jasmine从4.x版本开始原生支持ES模块,配置好
package.json的"type": "module"后,测试文件用ES模块语法,手动替换导出的函数来实现Mock:
// test1.test.js import { main, a } from './toto'; describe('main函数测试', () => { it('使用Mock的a函数返回正确值', () => { // 保存原函数,测试后恢复 const originalA = a; // 替换为Mock函数 globalThis.a = () => -2; expect(main()).toBe(-2); // 恢复原函数 globalThis.a = originalA; }); });
- 注意:Jasmine没有Jest那样的自动模块Mock能力,需要手动处理函数替换,适合模块结构简单的小型项目,胜在配置门槛低。
内容的提问来源于stack exchange,提问作者stack80
相关产品推荐
相关产品推荐

