Mock the aws-sdk using jest

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:

Powered by Blogger.