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:
How to mock S3 with jest? Jest Mock module per test
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()
}
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 s3 = 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 s3() // 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 a promise() as well as a catch block, hence I’m mocking those out too.
Hope this helps someone! Thank you for reading.