jest.mock在JS测试搭配TS模块时mock逻辑不生效问题
问题原因
核心诱因是模块加载顺序错误,和JS测试+TS源码的混合开发场景无关:
- Jest的
jest.mock调用默认会被提升(hoist)到文件顶部,但这个提升逻辑仅会优先于ES模块风格的import语句执行,不会提前到手动编写的CommonJSrequire调用之前。 - 现有测试代码先执行了
const { foo } = require('../src/foo/fooModule'),这行代码运行时会同步加载fooModule及其依赖的原始util模块,等后续执行jest.mock时,util模块已经完成加载,mock逻辑无法介入已经初始化的模块依赖树,自然不会执行传入的工厂函数。
如果调整顺序后仍不生效,可排查次要配置问题:TS配置中如果开启了baseUrl/paths路径别名,但Jest的moduleNameMapper没有同步对应规则,可能出现测试环境和源码环境解析到的util模块不是同一个文件的情况,但从当前给出的相对路径写法来看,该问题触发概率极低。
修复方案
二选一即可:
方案1:保留CommonJS语法,调整语句顺序
将jest.mock声明挪到所有require调用之前,保证mock逻辑在模块加载前完成注册:
// test/fooModule.test.js // 先注册mock,再加载被测模块 jest.mock('../src/util', () => { return { utilFunction: () => 'mocked' }; }); const { foo } = require('../src/foo/fooModule') describe('fooModule tests', () => { it('returns mocked util result', () => { expect(foo()).toBe('mocked'); }); });
方案2:改用ES模块语法
用import语句加载被测模块,Jest会自动将jest.mock提升到所有import之前执行,无需手动调整顺序:
// test/fooModule.test.js // 注意需确保babel/ts-jest配置支持ES模块解析 import { foo } from '../src/foo/fooModule' jest.mock('../src/util', () => { return { utilFunction: () => 'mocked' }; }); describe('fooModule tests', () => { it('returns mocked util result', () => { expect(foo()).toBe('mocked'); }); });
额外配置检查
如果上述修改后mock仍未生效,确认两项Jest配置:
moduleFileExtensions配置中包含ts、js后缀,可正确识别TypeScript源码文件- 若使用路径别名,
moduleNameMapper规则和tsconfig.json中的paths配置完全一致,避免模块解析错位
内容的提问来源于stack exchange,提问作者mowwwalker
相关产品推荐
相关产品推荐

