使用Jest单元测试Lambda函数时如何直接获取uploadToS3返回值
解决方案
你可以通过以下两种常用方案实现需求,两种方案都不需要修改生产环境下handler的返回逻辑,完全可以保留给步骤函数用的业务payload结构。
方案1:单独导出uploadToS3函数做单元测试
只需在Lambda源码中新增一行导出逻辑,不影响原有生产逻辑:
// app.js 末尾新增导出 exports.uploadToS3 = uploadToS3;
测试代码可以分别验证上传逻辑和handler返回的业务数据:
const S3Upload = require('../../app'); const AWS = require('aws-sdk') const s3 = new AWS.S3() let cat1 = { name : 'Bertie', breed : 'Cymric', color : 'white' } jest.mock('aws-sdk', () => { const putObjectOutputMock = { promise: jest.fn(), }; const putObjectMock = jest.fn(() => putObjectOutputMock); const mS3 = { putObject: putObjectMock, }; return { S3: jest.fn(() => mS3) }; }); describe('S3 upload test', () => { // 单独验证uploadToS3的执行结果 it('uploadToS3 should return correct s3 response', async () => { const mPutObjectResponse = { ETag: '"test-etag"', ServerSideEncryption: 'AES256' }; s3.putObject().promise.mockResolvedValueOnce(mPutObjectResponse); const mEvent = { queryStringParameters: { value: 'test' } }; // 直接拿到uploadToS3的返回值做断言 const uploadRes = await S3Upload.uploadToS3(mEvent); expect(uploadRes).toEqual(mPutObjectResponse); // 验证S3调用参数正确 expect(s3.putObject).toBeCalledWith({ Bucket: 'myBucket', Key: 'myKey', Body: JSON.stringify(cat1), ServerSideEncryption: "AES256", Tagging: 'myTags' }); }) // 验证handler返回的业务payload符合预期 it('lambdaHandler should return correct business data', async () => { const mEvent = { queryStringParameters: { value: 'test' }, body: { newStuff: 'stuff goes here', eventList: [] } }; const returnValue = await S3Upload.lambdaHandler(mEvent); // 这里只断言你实际需要返回的业务字段即可 expect(returnValue).toEqual({ name: '预期的name值', age: '预期的age值' }); }) })
方案2:通过jest.spyOn劫持方法调用(无需对外暴露内部函数)
如果不想把内部的uploadToS3函数对外导出,可以调整handler内的调用方式,让jest可以拦截到方法调用:
// app.js 中将uploadToS3的调用改为从exports对象上取 const upload = await exports.uploadToS3(event);
测试时直接监听方法调用即可拿到返回结果:
it('should get uploadToS3 result without export', async () => { // 监听uploadToS3调用 const uploadSpy = jest.spyOn(S3Upload, 'uploadToS3').mockResolvedValue({ ETag: '"mock-etag"', ServerSideEncryption: 'AES256' }); const mEvent = { queryStringParameters: { value: 'test' } }; const handlerRes = await S3Upload.lambdaHandler(mEvent); // 直接获取uploadToS3的返回值 const uploadResult = await uploadSpy.mock.results[0].value; expect(uploadResult.ETag).toBe('"mock-etag"'); // 验证handler返回的业务数据 expect(handlerRes).toEqual({ name: '预期的name值', age: '预期的age值' }); uploadSpy.mockRestore(); })
内容的提问来源于stack exchange,提问作者MountainBiker
相关产品推荐
相关产品推荐

