Jest监听全局函数时,被其他函数调用为何失效?
问题原因与解决方案
核心原因
在非模块化的全局代码环境中,main函数内部调用的spyOnMe是词法作用域内的直接引用,而非从window对象上查找的属性。
当你执行jest.spyOn(window, 'spyOnMe').mockReturnValue(mockedValue)时,仅修改了window.spyOnMe这个全局属性的指向,但main函数在定义时已经捕获了原始spyOnMe函数的引用——这个引用不会因为window上的属性被修改而改变。
直接调用spyOnMe()能拿到模拟值,是因为测试文件作用域中,spyOnMe默认指向window.spyOnMe(全局变量自动挂载到window),但main内部的调用始终使用定义时的原始函数引用。
解决方案
方案1:修改源码(推荐,符合全局环境规范)
调整main函数,明确从window调用spyOnMe,让后续修改window.spyOnMe能直接影响main的执行:
// ./src/index.js function spyOnMe() { return "Hello World!"; } function main() { const text = window.spyOnMe(); // 改为从window对象调用 return text; }
方案2:在测试环境中替换原始函数引用
如果无法修改源码,可在自定义testEnvironment预加载代码时,让main内部的函数引用指向window上的版本,或直接覆盖全局作用域的函数:
// ./src/index.spec.js it('should spyOn spyOnMe', () => { const mockedValue = 'Thanks for helping!'; // 直接替换全局作用域中的spyOnMe函数 global.spyOnMe = jest.fn().mockReturnValue(mockedValue); expect(spyOnMe()).toBe(mockedValue); const result = main(); expect(result).toBe(mockedValue); });
或者在自定义jest.env.js预加载时,将函数直接挂载为window属性,并让内部调用依赖这些属性:
// jest.env.js 预加载逻辑 window.spyOnMe = function spyOnMe() { return "Hello World!"; }; window.main = function main() { const text = window.spyOnMe(); return text; };
内容的提问来源于stack exchange,提问作者Gpack
相关产品推荐
相关产品推荐

