如何使用Jest多次Mock同一模块并设置不同返回值?
如何在Jest中多次Mock同一模块并设置不同返回值
这个需求在测试依赖外部配置或模块的函数时非常常见,核心要解决的是模块缓存的问题——因为Node.js的require会缓存已加载的模块,如果不清理缓存,之前的Mock值会一直影响后续测试。下面给你两种场景下的解决方案:
场景1:模块导出基本类型(比如你的示例中模块a导出数字)
因为基本类型是值传递,一旦add函数加载了模块a的值,后续修改Mock不会自动同步,所以需要每次测试都重置模块缓存、重新Mock并重新加载add函数:
describe('add', () => { // 每个测试结束后清除模块缓存,避免测试间互相干扰 afterEach(() => { jest.resetModules(); }); it('should add mock 1 to 2 and return 3', () => { // 本次测试Mock模块a返回1 jest.mock('./a', () => 1); // 必须在Mock之后再加载add函数,确保它使用最新的Mock值 const add = require('./add'); expect(add(2)).toBe(3); }); it('should add mock 5 to 3 and return 8', () => { // 本次测试Mock模块a返回5 jest.mock('./a', () => 5); const add = require('./add'); expect(add(3)).toBe(8); }); it('should add mock 10 to 7 and return 17', () => { jest.mock('./a', () => 10); const add = require('./add'); expect(add(7)).toBe(17); }); });
关键说明:
jest.resetModules():清空Jest的模块缓存,确保每次测试加载的都是全新的模块实例。- 必须在
jest.mock之后再require('./add'):因为add函数依赖模块a,只有先Mock模块a,add才会使用我们设置的Mock值。
场景2:模块导出引用类型(比如实际项目中的配置对象)
如果模块a导出的是对象(引用类型),我们可以直接修改Mock对象的属性,无需每次重新加载模块——因为add函数持有对该对象的引用,属性修改会实时生效:
假设模块a改为:
// a.js module.exports = { value: 1 };
add函数改为:
// add.js const a = require('./a'); function add(b) { return a.value + b; } module.exports = add;
对应的测试代码可以这样写:
describe('add', () => { let add; let mockConfig; beforeEach(() => { jest.resetModules(); // 创建一个可修改的Mock配置对象 mockConfig = { value: 1 }; jest.mock('./a', () => mockConfig); // 加载add函数 add = require('./add'); }); it('should use different mock values dynamically', () => { expect(add(2)).toBe(3); // 使用初始值1 // 直接修改Mock对象的属性,add会自动拿到最新值 mockConfig.value = 5; expect(add(3)).toBe(8); mockConfig.value = 10; expect(add(7)).toBe(17); }); });
关键说明:
- 这里依然用
jest.resetModules()确保每个测试的Mock对象是全新的,避免测试间的属性修改互相影响。 - 因为是引用类型,修改Mock对象的属性会直接反映到
add函数的依赖中,无需重新加载add。
内容的提问来源于stack exchange,提问作者Adrian Florescu
相关产品推荐
相关产品推荐

