jest.setMock对npm link模块的已安装依赖模拟失效问题求助
解决Jest Mock npm link模块中依赖的问题
我之前也碰到过类似的坑——当用npm link把本地模块关联到项目里时,Jest的mock总是不生效,核心原因是linked的模块会优先加载自身node_modules里的依赖,而不是我们在主项目里配置的mock。结合你的场景,给你几个靠谱的解决方案:
方案一:用moduleNameMapper全局映射依赖到mock文件
这是最稳妥的方法,让所有对my-dep的导入(不管是主项目里的还是linked的my-module里的)都指向我们的mock文件。
- 先在主项目
app根目录创建__mocks__文件夹,里面新建my-dep.js:
export const hello = () => { return 'mocked dude'; // 自定义你想要的mock返回值 };
- 修改
app里的jest.config.js(如果没有就新建),添加moduleNameMapper配置:
module.exports = { // 把所有my-dep的导入都指向我们的mock文件 moduleNameMapper: { '^my-dep$': '<rootDir>/__mocks__/my-dep.js' }, // 确保每次测试都重置mock,避免脏数据 resetMocks: true, // 因为my-module是linked的本地模块,需要让Jest转译它(默认Jest会忽略node_modules里的模块) transformIgnorePatterns: [ '/node_modules/(?!my-module)' ] };
- 然后在你的测试文件里直接使用即可,不需要额外的mock语句(不过加上
jest.mock('my-dep')更保险):
import { doSomething } from 'my-module'; jest.mock('my-dep'); test('测试doSomething使用mock的my-dep', () => { expect(doSomething()).toBe('mocked dude'); });
方案二:在测试文件里直接mock依赖(工厂函数方式)
如果不想全局配置,也可以在单个测试文件里直接用Jest的mock工厂函数来覆盖my-dep:
import { doSomething } from 'my-module'; // 直接mock my-dep,指定返回值 jest.mock('my-dep', () => ({ hello: jest.fn(() => 'mocked dude') })); test('doSomething返回mock后的结果', () => { expect(doSomething()).toBe('mocked dude'); // 还可以验证hello方法是否被调用 const { hello } = require('my-dep'); expect(hello).toHaveBeenCalled(); });
方案三:直接mockmy-module的导出(绕开依赖)
如果你的测试只关心doSomething的输出,不需要验证my-dep的调用,也可以直接mockmy-module本身:
jest.mock('my-module', () => ({ doSomething: jest.fn(() => 'mocked result') })); const { doSomething } = require('my-module'); test('doSomething返回预设的mock值', () => { expect(doSomething()).toBe('mocked result'); });
额外注意点
- 如果你用的是ES模块(比如
import/export),确保Jest配置了babel转译,比如安装babel-jest和@babel/preset-env,并在.babelrc里配置:
{ "presets": [["@babel/preset-env", { "targets": { "node": "current" } }]] }
- 测试前可以先清空模块缓存,避免旧的依赖残留:在测试文件开头加上
jest.resetModules();
内容的提问来源于stack exchange,提问作者Deepak
相关产品推荐
相关产品推荐

