0

I've defined a jest mock which mocks 'react-router-dom'. In my React Component Test, I'm using that mock to see if that has been called with "/". This is how I've mocked it:

const mockedUsedNavigate = jest.fn()
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => mockedUsedNavigate,
}))

I want to use the same mock in other component test files, is there a way I could do this? I tried creating __mocks___ directory and mocked it like this:

export const navigationMock = {
  useNavigate: jest.fn(),
}

But test failed when calling expect(navigationMock.useNavigate).toHaveBeenCalled() fails

Lin Du
  • 88,126
  • 95
  • 281
  • 483
Simmi George
  • 145
  • 1
  • 3
  • 12
  • Don't do that at all. Don't mock what you don't own, and don't partially mock things. Do something like this: https://stackoverflow.com/a/65275037/3001761. – jonrsharpe Apr 03 '22 at 07:50

1 Answers1

0

Don't mock useNavigate hook, incorrect mock may break the implementation. That's the one reason like @jonrsharpe said:

Don't mock what you don't own

Instead, you should use the MemoryRouter component for testing.

A <MemoryRouter> stores its locations internally in an array. Unlike <BrowserHistory> and <HashHistory>, it isn't tied to an external source, like the history stack in a browser. This makes it ideal for scenarios where you need complete control over the history stack, like testing.

E.g.

import * as React from "react";
import * as TestRenderer from "react-test-renderer";
import {
  MemoryRouter,
  Routes,
  Route,
  useNavigate
} from "react-router";

describe("useNavigate", () => {
  it("transitions to the new location", () => {
    function Home() {
      let navigate = useNavigate();

      function handleClick() {
        navigate("/about");
      }

      return (
        <div>
          <h1>Home</h1>
          <button onClick={handleClick}>click me</button>
        </div>
      );
    }

    let renderer: TestRenderer.ReactTestRenderer;
    TestRenderer.act(() => {
      renderer = TestRenderer.create(
        <MemoryRouter initialEntries={["/home"]}>
          <Routes>
            <Route path="home" element={<Home />} />
            <Route path="about" element={<h1>About</h1>} />
          </Routes>
        </MemoryRouter>
      );
    });

    let button = renderer.root.findByType("button");

    TestRenderer.act(() => {
      button.props.onClick();
    });

    expect(renderer.toJSON()).toMatchInlineSnapshot(`
      <h1>
        About
      </h1>
    `);
  });
Lin Du
  • 88,126
  • 95
  • 281
  • 483