aws-sdk-mock在Lambda函数内无法生效,单元测试中正常
解决aws-sdk-mock在Lambda函数中无法模拟DynamoDB/Cognito调用的问题
我之前也踩过这个坑——单元测试里mock明明生效,但一到Lambda函数执行就直接走真实接口,大概率是模块加载顺序或者mock注入时机出了问题,下面给你几个排查和解决的具体方向:
1. 必须让mock在aws-sdk加载前执行
aws-sdk-mock的核心原理是覆盖require('aws-sdk')返回的模块对象,如果你的Lambda函数在mock之前就已经加载了aws-sdk(比如在文件顶部直接require('aws-sdk')实例化了DynamoDB客户端),那mock就完全无法生效。
正确的测试文件顺序:
const AWSMock = require('aws-sdk-mock'); // 第一步:先执行mock操作 before(function(){ AWSMock.mock('DynamoDB.DocumentClient', 'put', function (params, callback){ console.log("mock called"); callback(null, "1234"); }); }); // 第二步:再引入你的Lambda函数 const userRegistrationLambda = require('../path/to/your/lambda-function'); describe('User email/phone registration test', function() { it('should handle registration correctly', async function() { // 编写你的测试逻辑 const result = await userRegistrationLambda.handler(event, context); // 断言验证结果 }); });
2. 检查是否使用了aws-sdk v3
如果你的项目用的是aws-sdk v3(比如依赖@aws-sdk/client-dynamodb、@aws-sdk/lib-dynamodb这类包),aws-sdk-mock对v3的支持非常有限,这时候得换用官方推荐的aws-sdk-client-mock工具。
v3版本的Mock示例(以DynamoDB DocumentClient为例):
const { mockClient } = require('aws-sdk-client-mock'); const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb'); // 创建mock客户端 const ddbMock = mockClient(DynamoDBDocumentClient); before(() => { // 模拟PutCommand的返回 ddbMock.on(PutCommand).resolves({ $metadata: { httpStatusCode: 200 } }); }); after(() => { // 测试后重置mock,避免污染其他用例 ddbMock.reset(); });
3. 测试后记得清理mock
如果不及时清理mock,可能会导致后续测试用例出现意外的mock残留,影响结果准确性:
after(function(){ // 清理指定服务的mock AWSMock.restore('DynamoDB.DocumentClient'); // 或者一次性清理所有mock // AWSMock.restore(); });
4. 验证mock的参数匹配
有时候mock没被触发,是因为Lambda调用DynamoDB时的参数和mock预期不匹配。可以在mock函数里打印接收的参数,排查是否存在参数不一致的情况:
AWSMock.mock('DynamoDB.DocumentClient', 'put', function (params, callback){ console.log("Mock收到的参数:", JSON.stringify(params, null, 2)); callback(null, "1234"); });
5. 排查打包工具的影响
如果你用Serverless Framework、Webpack这类工具打包测试代码,要确保aws-sdk被设为外部依赖,否则打包工具可能会把aws-sdk的真实代码打包进测试文件,导致mock无法覆盖:
// webpack.config.js示例 module.exports = { // 其他配置... externals: { 'aws-sdk': 'commonjs aws-sdk' } };
内容的提问来源于stack exchange,提问作者stephen1706
相关产品推荐
相关产品推荐

