Jest Mock导入外部文件常量时未生效,单元测试失败
问题原因与解决方案
问题核心是模块加载时机导致mock失效:
当测试代码运行时,constants.ts会在测试用例执行前就被导入,此时EXPORTED_CONSTANT会立即完成初始化,service.method()在这时候就已经执行了——而你的jest mock是在测试用例里才设置的,晚于常量初始化的时间,所以mock根本没机会生效,自然拿到的是原方法的返回值(这里是undefined)。
方案一:把常量改成函数,延迟执行
把常量包装成函数,让service.method()的调用延迟到函数执行时,这样mock设置好后再调用,就能生效。
修改constants.ts:
export const getExportedConstant = () => ({ value: service.method() });
修改test.ts里的测试函数:
export const testableFunction = async() => { return getExportedConstant(); };
测试代码不用改动,此时调用testableFunction会触发函数执行,使用已经mock好的service.method(),返回预期值。
方案二:动态导入模块,确保mock先生效
利用jest的模块重置功能,先设置mock,再重新导入模块,让常量初始化时使用mock后的方法。
修改测试代码:
it('message trigger for sendInteractiveWhatsapp', async () => { jest.resetModules(); // 重置所有已加载的模块,避免缓存影响 // 先设置mock jest.spyOn(service, 'method').mockImplementation(async () => { return "some_value"; }); // 动态导入测试目标模块,此时constants.ts会重新加载,常量初始化时用mock方法 const { testableFunction } = await import('./test.ts'); expect(await testableFunction()).toEqual({value: 'some_value'}); });
注意:如果service是单独的模块,需要确保mock在导入constants.ts前完成设置。
方案三:用getter属性延迟计算
把value改成getter,这样每次访问该属性时才会调用service.method(),而不是初始化时就执行。
修改constants.ts:
export const EXPORTED_CONSTANT = { get value() { return service.method(); } };
此时testableFunction和测试代码都不用改动,当expect比较对象的value属性时,会触发getter调用,此时mock已经生效,就能拿到预期的some_value。
内容的提问来源于stack exchange,提问作者Vaibhav Bhatnagar
相关产品推荐
相关产品推荐

