I found it a bit hard to find out how to mock AWS S3 while using Jest. So, I thought I’d document it here.
Useful Stack Overflow answers:
Here’s the code we will be testing
const AWS = require('aws-sdk')
// a function that returns a promise
function copyFileToS3() {
// initialise AWS S3
const s3 = new AWS.S3({
accessKeyId: 'whatever',
secretAccessKey: 'whatever',
endpoint: 'http://localhost:4566', // localstack is running on port 4566. Imagine this was the real S3 endpoint
s3ForcePathStyle: true,
})
const copyObjectParams = {
Bucket: 'some-bucket',
CopySource: 'some-bucket/some/path/myfile.json,
Key: 'some-bucket/some/other/path/myfile.json',
}
return s3.copyObject(copyObjectParams).promise()
}
module.exports = copyFileToS3
Here’s a unit test for the code above using Jest
We’ll be mocking S3, and asserting that S3’s copyObject function gets called with the right parameters.
Obviously, this is a simplistic function with hard-coded values, but the test is valid for a function that maybe does some transformation to the destination key, or does some validation on the CopySource, etc.
const copyFileToS3 = require('./s3') // This is the file where we use aws-sdk's S3 CopyObject method
const mockS3Instance = {
copyObject: jest.fn().mockReturnThis(),
promise: jest.fn().mockReturnThis(),
catch: jest.fn(),
}
jest.mock('aws-sdk', () => {
return { S3: jest.fn(() => mockS3Instance) }
})
describe('S3', () => {
it('calls aws-sdk copyObject method with correct parameters, async () => {
await copyFileToS3() // This is the function that uses the copyObject method
expect(mockS3Instance.copyObject).toHaveBeenCalledWith({
Bucket: 'some-bucket',
CopySource: 'some-bucket/some/path/myfile.json,
Key: 'some-bucket/some/other/path/myfile.json',
})
expect(mockS3Instance.copyObject).toHaveBeenCalledTimes(1)
})
})Some things to note
In the mockS3Instance I am using .mockReturnThis(). This is used to allow for chaining it to another method (in this case, promise which gets called like so: s3.copyObject(params).promise() in my code.
In the mockS3Instance, I have keys for promise and catch. This is because I was chaining copyObject with promise() as well as a catch block, hence I’m mocking those out too.
Hope this helps someone!