Jest中AWS Lambda.invoke() Mock失效,触发真实调用报错
我之前也碰到过一模一样的问题——用aws-sdk-mock mock DynamoDB完全正常,但Lambda的invoke就是会走真实调用,触发权限错误。结合你贴的代码,我梳理了几个核心问题和修复方案:
1. 导入顺序搞反了!这是最常见的坑
aws-sdk-mock的原理是替换AWS SDK类的原型方法,必须在被测试模块加载之前执行mock,不然被测试文件里的new Lambda()会提前创建真实实例,mock根本拦截不到。
看你的测试代码,应该是先导入了myTest模块,再做的mock?赶紧调整顺序:先mock Lambda,再导入被测试的模块。比如:
import AWSMock from 'aws-sdk-mock'; import { Context } from 'aws-lambda'; // 先定义context模拟函数 const context = () => ({ callbackWaitsForEmptyEventLoop: false, functionName: 'test-function', awsRequestId: 'test-request-id', // 其他context字段按需补充 }); describe('Mock Lambda', () => { let myTest; beforeAll(async () => { // 第一步:先mock Lambda的invoke方法 AWSMock.mock('Lambda', 'invoke', (params, callback) => { if (params.FunctionName === 'MyLambaInvocation') { // 注意:Lambda.invoke的返回结构要符合真实AWS响应格式 callback(null, { StatusCode: 200, Payload: JSON.stringify({ code: '0', message: 'Successful' }) }); } else { callback(new Error('Unknown Lambda function'), null); } }); // 第二步:再导入被测试模块 myTest = await import('../path/to/your/myTest-file'); }); afterAll(() => { // 测试完记得恢复,避免影响其他测试用例 AWSMock.restore('Lambda'); }); it('should mock Lambda invoke successfully', async () => { const testEvent = {}; // 替换成你的测试事件 const result = await myTest.handler(testEvent, context(), null); // 这里加断言验证结果 expect(result.statusCode).toBe(200); expect(JSON.parse(result.body)).toEqual({ code: '0', message: 'Successful' }); }); });
2. 你测试代码里有语法错误!
看你贴的测试代码,await myTest.handler(...)居然写在AWSMock.mock()的回调函数里了?这会导致handler根本不会被正确调用,而且mock的逻辑也完全混乱了。一定要把handler的调用移到mock设置完成之后的测试用例里,或者beforeAll的mock外面。
3. 检查Lambda的响应格式是否正确
你mock的返回是{ status: 200, data: {...} },但真实的Lambda.invoke响应结构是{ StatusCode: number, Payload: string }(Payload是JSON字符串)。如果你的业务代码里是解析Payload来获取数据,那mock的格式不对会导致逻辑出错,甚至看起来像是mock没生效。
4. 确认离线环境的配置不干扰mock
你的invokeLambda函数里根据IS_OFFLINE设置了endpoint,如果测试时这个环境变量是true,会不会导致mock失效?其实aws-sdk-mock会覆盖所有实例的方法,不管endpoint是什么,但保险起见可以在测试时明确设置process.env.IS_OFFLINE = 'false',或者在mock里打印params确认是否接收到调用。
最后再排查版本兼容性
如果你用的是AWS SDK v3,那aws-sdk-mock是不兼容的(它只支持v2),得换成aws-sdk-client-mock。但从你的代码import { Lambda } from 'aws-sdk'来看,是v2,所以这个问题应该不存在,但可以检查下aws-sdk-mock的版本是不是最新的,避免版本兼容问题。
按上面的步骤调整后,应该就能正常mock Lambda.invoke了,不会再触发真实调用的权限错误。
内容的提问来源于stack exchange,提问作者jl90

