Home > OS >  Mock a function used inside a react component "multiple times"
Mock a function used inside a react component "multiple times"

Time:05-02

I am currently mocking an internal dependency in a react project this way:

import { QueryClient, QueryClientProvider } from "react-query";
import { render } from "@testing-library/react";
import SectionCourses from "./SectionCourses";

const queryClient = new QueryClient({});

jest.mock("@myORG/axiosWrapperReactQuery", () => {
  const original = jest.requireActual("@myORG/axiosWrapperReactQuery");
  return {
    ...original,
    getAllCourses: jest.fn().mockImplementation(() => ({
      isLoading: false,
      typedData: [],
    })),
  };
});

it("not found", async () => {
  const { findByText } = render(
    <QueryClientProvider client={queryClient}>
      <SectionCourses />
    </QueryClientProvider>
  );

  const firstCourse = await findByText("No courses found");
  expect(firstCourse).toBeInTheDocument();
});

It works perfectly but when I try to mock the dependency again in the same file it fails

// ALL THE PREVIOUS CODE

jest.mock("@myORG/axiosWrapperReactQuery", () => {
  const original = jest.requireActual("@myORG/axiosWrapperReactQuery");
  return {
    ...original,
    getAllCourses: jest.fn().mockImplementation(() => ({
      isLoading: true, // This was changed to true
      typedData: [],
    })),
  };
});

it("is loading", async () => {
  const { findByText } = render(
    <QueryClientProvider client={queryClient}>
      <SectionCourses />
    </QueryClientProvider>
  );

  const firstCourse = await findByText("Loading...");
  expect(firstCourse).toBeInTheDocument();
});

It seems that only takes the last jest.mock

enter image description here

So what will be the way to handle this if I need to mock that funcion many times so I can see what my React Component will display?

I know I can create multiple files like SectionCourses-V1.test.tsx, SectionCourses-V2.test.tsx... but having so many files it's not ideal

Note: This is not a duplicate of Jest -- Mock a function called inside a React Component

CodePudding user response:

You can move the implementation of mock inside the test method itself so that each test method works on the provided mock implementation.

it("not found", async () => {
  jest.mock("@myORG/axiosWrapperReactQuery", () => {
    const original = jest.requireActual("@myORG/axiosWrapperReactQuery");
    return {
      ...original,
      getAllCourses: jest.fn().mockImplementation(() => ({
        isLoading: true, // This was changed to true
        typedData: [],
      })),
    };
  });

  const { findByText } = render(
    <QueryClientProvider client={queryClient}>
      <SectionCourses />
    </QueryClientProvider>
  );

  const firstCourse = await findByText("No courses found");
  expect(firstCourse).toBeInTheDocument();
});




it("is loading", async () => {
  jest.mock("@myORG/axiosWrapperReactQuery", () => {
    const original = jest.requireActual("@myORG/axiosWrapperReactQuery");
    return {
      ...original,
      getAllCourses: jest.fn().mockImplementation(() => ({
        isLoading: true, // This changed to true
        typedData: [],
      })),
    };
  });
  const { findByText } = render(
    <QueryClientProvider client={queryClient}>
      <SectionCourses />
    </QueryClientProvider>
  );

  const firstCourse = await findByText("Loading...");
  expect(firstCourse).toBeInTheDocument();
});

CodePudding user response:

You can chain the mock implementations of getAllCourses jest docs

Try this,

jest.mock("@myORG/axiosWrapperReactQuery", () => {
const original = jest.requireActual("@myORG/axiosWrapperReactQuery");
return {
  ...original,
  getAllCourses: jest.fn()
                 .mockImplementationOnce(() => ({
                             isLoading: false, // 1st call
                             typedData: [],
                 }))
                 .mockImplementationOnce(() => ({
                             isLoading: true, // 2nd call
                             typedData: [],
                 }))
}
  • Related