You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:15:49