如何覆盖jest.config.js中setupFiles定义的jest.mock以修改isMobile值?
解决Jest全局Mock后局部覆盖isMobile无效的问题
这问题我做项目时也踩过坑,全局Mock之后直接用jest.mock或者mockImplementation确实容易不生效,主要是Jest的Mock提升机制和模块缓存在搞鬼,给你几个靠谱的解决方法:
方法一:用jest.doMock替代jest.mock
jest.mock会被自动提升到当前文件最顶部执行,而jest.doMock不会,它会在代码执行到它的时候才生效。需要注意的是,要重新导入模块(因为之前的导入已经用了全局Mock的版本):
// 在需要覆盖的测试用例/describe块内 test('测试移动端场景下的逻辑', () => { // 局部Mock成true jest.doMock('xxx/layout', () => ({ isMobile: true })); // 重新导入模块,获取最新的Mock值 const { isMobile } = require('xxx/layout'); // 现在isMobile就是true了 expect(isMobile).toBe(true); });
方法二:全局Mock时把isMobile设为可修改的Jest函数
如果你的isMobile是一个函数(从你提到mockImplementation推测可能是这种情况),可以在全局的jest.init.js里把它定义为jest.fn(),这样后续就能轻松修改它的返回值:
第一步:修改全局Mock配置(jest.init.js)
jest.mock('xxx/layout', () => ({ // 默认返回false,同时把它变成可修改的Mock函数 isMobile: jest.fn().mockReturnValue(false) }));
第二步:在测试用例里修改返回值
// 先导入模块 const { isMobile } = require('xxx/layout'); test('覆盖为移动端状态', () => { // 修改Mock函数的返回值 isMobile.mockReturnValue(true); expect(isMobile()).toBe(true); }); test('恢复默认的非移动端状态', () => { isMobile.mockReturnValue(false); expect(isMobile()).toBe(false); });
方法三:清除模块缓存后重新Mock
如果上面两种方法都不适用,可以先清除模块缓存,再重新Mock并导入:
test('局部覆盖isMobile变量', () => { // 清除所有已加载模块的缓存 jest.resetModules(); // 重新Mock模块 jest.mock('xxx/layout', () => ({ isMobile: true })); // 导入最新Mock后的模块 const { isMobile } = require('xxx/layout'); expect(isMobile).toBe(true); });
为什么原来的方法无效?
jest.mock会被Jest自动提升到文件最顶部,早于setupFiles里的全局Mock执行,但模块一旦被缓存,后续的Mock不会生效;- 如果
isMobile是普通变量而非函数,mockImplementation根本无法生效,因为它只针对Mock函数。
内容的提问来源于stack exchange,提问作者sebap
相关产品推荐
相关产品推荐

