Hi ✋,
The hardest part of writing the unit test is creating mocks for external libraries, the purpose of this article is to help someone who has problems mocking a library like this.
Today I'm going to code how to mock your lambda invoke function in 'aws-sdk' using a jest 💪.
I'm going to write test cases for the below code. This is a simple cache service provider. it contains a getter and a setter.
CacheServiceProvider.ts
import { Lambda } from "aws-sdk";
export enum Action {
Get = "get",
Delete = "delete",
Keys = "keys",
Set = "set",
}
export default class CacheServiceProvider {
private lambda: Lambda;
async set(key: string, value: string, expire: number): Promise<string> {
return this.invoke({
action: Action.Set,
key,
value,
expire,
}).then(
(data: Lambda.InvocationResponse) => {
const response = JSON.parse(data.Payload.toString());
return response.body.data;
},
(err) => {
return err;
}
);
}
async get(key: string): Promise<string> {
return this.invoke({
action: Action.Get,
key,
}).then(
(data: Lambda.InvocationResponse) => {
const response = JSON.parse(data.Payload.toString());
return response.body.data;
},
(err) => {
return err;
}
);
}
private async invoke(body: object): Promise<Lambda.InvocationResponse> {
return await this.lambda
.invoke({
FunctionName: "my-function-name",
InvocationType: "RequestResponse",
Payload: JSON.stringify({
body,
}),
})
.promise();
}
constructor() {
this.lambda = new Lambda();
}
}
In here, I want to mock lambda.invoke function and want to set different responses to the promise resolve/reject.
This is my CacheServiceProvider.test.ts
import CacheServiceProvider from "./CacheServiceProvider";
let provider: CacheServiceProvider;
const key = "TestKey";
const value = "TestValue";
provider = new CacheServiceProvider();
const fakePromise = {
promise: jest.fn(),
};
jest.mock("aws-sdk", () => ({
Lambda: jest.fn(() => ({
invoke: () => fakePromise,
})),
}));
describe("CacheHelperServiceProvider", () => {
beforeEach(() => {
jest.clearAllMocks();
});
it("Should be able to set and get value using a key", async () => {
fakePromise.promise = jest.fn().mockImplementation(() =>
Promise.resolve({
Payload: JSON.stringify({
body: {
data: value,
},
}),
})
);
const setResponse = await provider.set(key, value, 10);
expect(setResponse).toStrictEqual(value);
const getResponse = await provider.get(key);
expect(getResponse).toStrictEqual(value);
});
it("Should throw an error when using different key", async () => {
fakePromise.promise = jest
.fn()
.mockImplementation(() => Promise.reject(new Error()));
try {
await provider.get(key);
} catch (error) {
expect(error).toBeDefined();
}
});
});
Here I have fakePromise function and I can use jest mockImplementation method when
I want to set response to the lambda.invoke().promise() 😁.
If you need to change promise response , then you have to mock invoke function like invoke: () => fakePromise in the jest.mock("aws-sdk").
If this article helped you, please leave a comment. and also please leave your suggestions.
No comments: