Home > Software engineering >  How mock a function with an Promise inside in Javascript
How mock a function with an Promise inside in Javascript

Time:12-06

This is my helper function in src/utils/calls/aws.js

export const loginCognito = (cognitoUser, authenticationDetails) => {
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: function (result) {
      return result;
    },
    onFailure: function (error) {
      return error;
    },
  });
};

This is my test file:

import { loginCognito } from "../../../utils";

describe("Test LoginPage", () => {

  it("Can press button without userEvent", async () => {

    loginCognito = jest.fn().mockResolvedValue({accessToken: "a2b3"});

    renderWithProviders(<LoginPage />);

    const inputUsername = screen.getByLabelText(/username/i);
    fireEvent.change(inputUsername, {
      target: {
        value: "[email protected]",
      },
    });

    const inputPassword = screen.getByLabelText(/password/i);
    fireEvent.change(inputPassword, {
      target: {
        value: "thisIsASecretPassword",
      },
    });

    const loginButton = screen.getByRole("button", { name: /login/i });
    fireEvent.click(loginButton);
    await waitFor(() => {
      expect(localStorage.getItem(LOCALSTORAGE_ACCESS_TOKEN)).toEqual(
        accessToken
      );
    });
  });
});

But I get "loginCognito" is read-only.

So, basically, I want skip real implementation of loginCognito (it calls AWS under the hood) and return a value.

Thank you

CodePudding user response:

You can't reassign the value of loginCognito because you're trying to reassign a constant variable. Instead, you can mock the loginCognito function by using jest.mock in your test file. Here's how you can do that:

  1. At the top of your test file, add the following line to mock the loginCognito function:
jest.mock('../../../utils/calls/aws', () => {
  return {
    loginCognito: jest.fn(() => Promise.resolve({ accessToken: 'a2b3' })),
  };
});
  1. Import the loginCognito function from the mocked module instead of the real module:

import { loginCognito } from "../../../utils/calls/aws";

This should allow you to mock the loginCognito function and avoid calling the real AWS authentication process in your tests.

Note: In the mock function, you'll need to return a promise that resolves to the desired value (in this case, an object with an accessToken property set to 'a2b3'). This is because the loginCognito function in your code returns a promise.

  • Related