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

Jest模拟函数未被调用排查:AWS Lambda单元测试异常

Jest Mock AWS DynamoStore模块不生效问题解决

问题概述

在为AWS Node.js Lambda配置Jest测试时,尝试Mock被多个Lambda共享的dynamoStore模块,但jest.fn的自定义实现始终未被调用。调试发现Lambda代码中的getVehicleMetaKeysFromDeviceId()是Jest Mock对象,但调用时未使用自定义Mock逻辑,导致测试中vehicle_ids为undefined。

相关代码示例

dynamoStore/vehicleMetaConstraints.js

exports.getVehicleMetaKeysFromDeviceId= async (data) => {
  return data
};

dynamoStore/index.js

exports.vehicleMetaConstraints = require("./vehicleMetaConstraints");
// 其他导出...

lambda1/index.js

const { vehicleMetaStore } = require("dynamo-store");

exports.handler = async (event, context, callback) => {
    const message = event;
  
    let vehicle_ids = await vehicleMetaStore.getVehicleMetaKeysFromDeviceId(message.id);
    // 测试时vehicle_ids为undefined
}

lambda1/index.test.js

const { vehicleMetaStore } = require("dynamo-store");

jest.mock("dynamo-store", () => {
  return {
    vehicleMetaStore: {
      getVehicleMetaKeysFromDeviceId: jest.fn(),
    },
  };
});

describe("VehicleStorageLambda", () => {
  beforeEach(() => {
    jest.resetModules();
    process.env = { ...env };
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  test("Handles first time publish with existing device", async () => {
    let functionHandler = require("./index");
    vehicleMetaStore.getVehicleMetaKeysFromDeviceId.mockImplementationOnce(() =>
      // 此逻辑从未被调用
      Promise.resolve({
        device_id: "333936303238510e00210022",
      })
    );

    await functionHandler.handler({});
  });
});

问题根源与修复方案

1. 模块导出与导入命名不匹配

dynamoStore/index.js导出的是vehicleMetaConstraints,但Lambda代码和测试代码中都尝试导入vehicleMetaStore,这是核心错误之一。

修正方式:

  • 调整Lambda代码的导入语句,匹配实际导出名称:
    // lambda1/index.js
    const { vehicleMetaConstraints: vehicleMetaStore } = require("dynamo-store");
    
  • 或修改dynamoStore/index.js的导出名称:
    // dynamoStore/index.js
    exports.vehicleMetaStore = require("./vehicleMetaConstraints");
    

2. jest.resetModules()导致Mock被重置

测试中beforeEach里的jest.resetModules()会重置所有已加载的模块,包括之前通过jest.mock创建的Mock模块。后续在test中require("./index")时,会重新加载未被Mock的原始模块,导致自定义Mock逻辑失效。

修正方式:

方案A:移除jest.resetModules()

修改测试文件的beforeEach:

beforeEach(() => {
  process.env = { ...env };
});

方案B:重置后重新Mock(若必须保留jest.resetModules())

调整测试流程,在重置模块后重新执行Mock,并在Mock完成后再加载Lambda handler:

describe("VehicleStorageLambda", () => {
  let vehicleMetaStore;
  let functionHandler;

  beforeEach(() => {
    jest.resetModules();
    process.env = { ...env };
    
    // 重新Mock模块
    jest.mock("dynamo-store", () => {
      return {
        vehicleMetaStore: {
          getVehicleMetaKeysFromDeviceId: jest.fn(),
        },
      };
    });
    
    // 加载Mock后的模块和Lambda handler
    ({ vehicleMetaStore } = require("dynamo-store"));
    functionHandler = require("./index");
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  test("Handles first time publish with existing device", async () => {
    vehicleMetaStore.getVehicleMetaKeysFromDeviceId.mockImplementationOnce(() =>
      Promise.resolve({
        device_id: "333936303238510e00210022",
      })
    );

    await functionHandler.handler({ id: "test-id" });
    // 添加断言验证Mock被调用
    expect(vehicleMetaStore.getVehicleMetaKeysFromDeviceId).toHaveBeenCalledWith("test-id");
  });
});

3. 确保Mock时机正确

必须在加载Lambda handler之前完成Mock配置,否则handler会加载原始模块而非Mock版本。调整测试中require("./index")的时机,确保在mockImplementationOnce之后或者Mock已初始化完成后再加载handler。

内容的提问来源于stack exchange,提问作者Chris Chevalier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 00:15:59