Jest为命名导出函数替换Mock实现失效及模块缓存问题排查
Jest测试AWS Lambda异步函数Mock跨用例失效的解决方法
问题本质
Node.js模块加载机制会缓存已导入的模块,如果你在测试文件顶部提前导入了Lambda的handler,后续测试用例中对getConfig的mock变更不会作用到已缓存的handler实例上,导致多个测试用例复用同一个mock值;而初始mock无效则是因为mock操作晚于handler的导入,使得handler使用的是原始的getConfig函数而非mock版本。
分步解决方案
1. 重构测试代码,动态导入模块
不要在文件开头静态导入handler和依赖模块,而是在每个测试用例(或beforeEach钩子)中先清除缓存、mock依赖,再动态导入:
describe('Lambda Handler Tests', () => { beforeEach(() => { // 重置所有模块缓存,确保每次测试都重新加载模块 jest.resetModules(); // 提前mock getConfig模块 jest.mock('./config', () => ({ getConfig: jest.fn() })); }); test('返回预期配置A', async () => { const { getConfig } = require('./config'); // 为当前测试设置专属mock返回值 getConfig.mockResolvedValue({ env: 'dev', apiKey: 'key-dev' }); // 动态导入handler,确保使用mock后的getConfig const { handler } = require('./index'); const response = await handler(); expect(response).toEqual({ env: 'dev', apiKey: 'key-dev' }); }); test('返回预期配置B', async () => { const { getConfig } = require('./config'); // 为当前测试设置另一组mock返回值 getConfig.mockResolvedValue({ env: 'prod', apiKey: 'key-prod' }); // 重新导入handler const { handler } = require('./index'); const response = await handler(); expect(response).toEqual({ env: 'prod', apiKey: 'key-prod' }); }); });
2. 核心注意事项
jest.resetModules()是关键:该方法会清除Node.js模块缓存,让每次测试都重新加载index.js和它的依赖,彻底隔离不同测试用例的模块实例- 先mock,再导入handler:必须确保在导入
handler之前完成对getConfig的mock,这样handler加载时才会使用mock后的函数 - 每个测试独立设置mock:在每个测试用例中单独指定
getConfig的返回值,避免用例间的mock污染
3. 解决初始mock返回undefined的问题
之前await getConfig返回undefined,是因为你在导入handler之后才进行mock操作,此时handler已经绑定了原始的getConfig函数。按照上面的顺序,先mock依赖模块,再导入handler,就能确保handler使用的是mock后的函数,不会再返回undefined。
内容的提问来源于stack exchange,提问作者Andrei Khotko
相关产品推荐
相关产品推荐

