使用Jest模拟同一AWS Lambda函数中的两个S3 API调用



我正试图模拟同一Lambda函数中的两个S3调用,但似乎出现了Access Denied错误,所以这让我相信S3调用没有被模拟。我目前使用的语法在模拟函数中的一个S3调用时有效,但我目前测试的函数有两个S3调用(deleteObject和putObject(。

这是我的模拟代码:

const putObjectMock = jest.fn(() => ({
promise: jest.fn(),
}));
const deleteObjectMock = jest.fn(() => ({
promise: jest.fn(),
})));
jest.mock("aws-sdk", () => ({
S3: jest.fn(() => ({
deleteObject: deleteObjectMock,
putObject: putObjectMock,
})),
}));

还有我的测试:

const newHandler = Handler.handler
const returnValue = await handler ({
queryStringParameters: {
eventListValue: "test",
eventListName: "test2",
body: {newStuff: "stuff goes here", eventList: [] },
});
expect(returnValue).toEqual({
statusCode:200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true,
},
body: undefined
})
});

文件中有两个S3调用的部分:

if(event.queryStringParameters.value){
await s3.deleteObject({Bucket: "my-bucket-name", Key: "name-of-object", 
}).promise()
}
const putObjectResponse = await s3.putObject({Bucket: "my-bucket-name", Key: 
"name-of-object",
ContentType: "application/json", Body: event.body}).promise();

当我尝试测试此项时,返回拒绝访问。任何帮助都会很棒。

这是单元测试解决方案:

handler.js:

import AWS from 'aws-sdk';
const s3 = new AWS.S3();
export async function handler(event) {
if (event.queryStringParameters.value) {
await s3.deleteObject({ Bucket: 'my-bucket-name', Key: 'name-of-object' }).promise();
}
const putObjectResponse = await s3
.putObject({ Bucket: 'my-bucket-name', Key: 'name-of-object', ContentType: 'application/json', Body: event.body })
.promise();
return putObjectResponse;
}

handler.test.js:

import { handler } from './handler';
import AWSMock from 'aws-sdk';
jest.mock('aws-sdk', () => {
const putObjectOutputMock = {
promise: jest.fn(),
};
const putObjectMock = jest.fn(() => putObjectOutputMock);
const deleteObjectOutputMock = {
promise: jest.fn(),
};
const deleteObjectMock = jest.fn(() => deleteObjectOutputMock);
const mS3 = {
deleteObject: deleteObjectMock,
putObject: putObjectMock,
};
return { S3: jest.fn(() => mS3) };
});
describe('61719699', () => {
it('should delete object and put object', async () => {
const mS3 = new AWSMock.S3();
const mPutObjectResponse = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: undefined,
};
mS3.putObject().promise.mockResolvedValueOnce(mPutObjectResponse);
const mEvent = { queryStringParameters: { value: 'test' }, body: { newStuff: 'stuff goes here', eventList: [] } };
const returnValue = await handler(mEvent);
expect(returnValue).toEqual({
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: undefined,
});
expect(mS3.deleteObject).toBeCalledWith({ Bucket: 'my-bucket-name', Key: 'name-of-object' });
expect(mS3.deleteObject().promise).toBeCalled();
expect(mS3.putObject).toBeCalledWith({
Bucket: 'my-bucket-name',
Key: 'name-of-object',
ContentType: 'application/json',
Body: { newStuff: 'stuff goes here', eventList: [] },
});
});
});

带覆盖率报告的单元测试结果:

PASS  stackoverflow/61719699/handler.test.js (10.22s)
61719699
✓ should delete object and put object (7ms)
------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |     100 |    66.67 |     100 |     100 |                   
handler.js |     100 |    66.67 |     100 |     100 | 6                 
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.94s

问题是因为我在代码文件中使用了特定的服务导入,而不是顶级导入。

已更改

const S3 = require("aws-sdk/clients/s3");

const AWS = require("aws-sdk");

最新更新