Reputation: 103
I am trying to mock a module, here S3 from aws-sdk.
The only way I could make it work was like that:
jest.mock('aws-sdk', () => {
return {
S3: () => ({
putObject: jest.fn()
})
};
});
The issue with that is that I don't have access to the S3 or putObject as a mock variable that I can check if called for testing purpose.
So I would like to do something like that:
const putObject = jest.fn();
jest.mock('aws-sdk', () => {
return { S3: () => ({ putObject }) };
});
I always do that for other modules and it works perfectly, it even works for lambda, but not for this case.
To me, the two codes look exactly the same so I really don't understand what is going on and why it does not work exactly the same way.
When I console log the s3 in the code that I want to test, I get that:
{ putObject: undefined }
Also, I use TypeScript so I can't just import the modules in the test file and mockReturnValue it if it's not a mock variable.
Thanks for your help!
EDIT:
Here is a reproducible minimal example of the problem:
uploadFile.ts
import AWS from 'aws-sdk';
const s3 = new AWS.S3();
export const uploadFile = async (key, body) => {
try {
await s3
.putObject({
Bucket: 'myBucket',
Key: key,
Body: body,
})
.promise();
} catch (error) {
console.log(error);
}
};
uploadFile.test.ts
import { uploadFile } from './uploadFile';
const mockPutObject = jest.fn(() => ({ promise: jest.fn() }));
jest.mock('aws-sdk', () => {
return { S3: () => ({ putObject: mockPutObject }) };
});
describe('Test uploadFile', () => {
it('should call putObject', () => {
uploadFile('key', { test: 'test' });
expect(mockPutObject).toHaveBeenCalled();
});
});
Upvotes: 2
Views: 2533
Reputation: 587
I was able to make it work this way:
import * as AWS from 'aws-sdk';
import { uploadFile } from '.';
const mockPutObject = jest.fn().mockImplementation((data) => {
return {
promise: () => jest.fn()
}
});
jest.mock('aws-sdk', () => {
return {
S3: function () {
return {
putObject: (data: any) => mockPutObject(data)
}
}
};
});
describe('Test uploadFile', () => {
it('should call putObject', () => {
uploadFile('key', { test: 'test' });
expect(mockPutObject).toHaveBeenCalledTimes(1);
expect(mockPutObject).toHaveBeenCalledWith({
Bucket: 'myBucket',
Key: 'key',
Body: {
test: 'test'
},
});
});
});
There are a few challenges that you might not have:
() => {...}
to function () { ... }
mockPutObject
as it is not yet initialized when it is building the mockpromise()
mock as well to work with your index.ts
Upvotes: 4