Jest模块内函数Mock失效:testBar未使用Mock的testBar1
解决Jest模块内函数相互调用时Mock失效的问题
问题原因
你遇到的问题核心在于:模块内部的函数调用是直接引用本地定义的函数,而非通过模块的导出对象。你用jest.mock替换了模块导出的testBar1,但testBar里调用的是模块内直接定义的原始testBar1,根本没用到你Mock的导出版本,所以Mock不生效。
解决方案
方案一:修改模块内部引用方式,通过导出对象调用函数
调整Tools.ts的代码,让testBar通过模块的导出对象来调用testBar1,这样就能让Mock的导出版本生效:
// Tools.ts export const testBar1 = () => { return 'original test2'; }; export const testBar = () => { // 改为通过exports调用testBar1 return 'test' + exports.testBar1(); };
或者使用模块自身的导入引用(适配ES模块规范):
// Tools.ts import * as self from './Tools'; export const testBar1 = () => { return 'original test2'; }; export const testBar = () => { return 'test' + self.testBar1(); };
此时你原来的测试代码就能正常工作,Mock的testBar1会被testBar调用。
方案二:使用jest.spyOn动态Mock导出函数
不需要修改原模块代码的前提下,用jest.spyOn来Mock模块导出的testBar1,同时确保测试时调用的是模块导出的testBar(避免解构导入导致的引用快照问题):
// Tools.test.ts import * as Tools from './Tools'; test('should mock functions correctly', () => { // SpyOn并Mock返回值 const mockTestBar1 = jest.spyOn(Tools, 'testBar1').mockReturnValue('mocked test2'); // 调用模块导出的testBar const result = Tools.testBar(); expect(result).toBe('testmocked test2'); // 测试完成后恢复原始函数 mockTestBar1.mockRestore(); });
注意:这种方法需要配合方案一的模块内部引用修改,否则testBar还是会调用本地原始的testBar1。
方案三:重构代码,拆分模块(推荐长期方案)
把testBar1抽离到单独的子模块,降低模块内耦合度,这样Mock会更直观,也符合单一职责原则:
// utils.ts export const testBar1 = () => { return 'original test2'; };
// Tools.ts import { testBar1 } from './utils'; export const testBar = () => { return 'test' + testBar1(); };
测试时直接Mockutils模块的testBar1即可:
// Tools.test.ts import { testBar } from './Tools'; jest.mock('./utils', () => ({ testBar1: jest.fn(() => 'mocked test2') })); test('should mock functions correctly', () => { const result = testBar(); expect(result).toBe('testmocked test2'); });
这种方式不需要修改原函数的调用逻辑,模块职责更清晰,Mock也更可靠。
内容的提问来源于stack exchange,提问作者iglushkov
相关产品推荐
相关产品推荐

