
To mock React-Router-Dom hooks in React you need to do the following:
- Mock the library React-Router-Dom using jest.mock
- Import non-mocked React-Router-Dom, so that we can use the rest of the non-mocked hooks
- Mock the required hook (
useNavigate
,userParam
…etc) usingjest.fn
Example
The following example shows a single button that navigate the user to a different page once the button is clicked:
import React from "react";
import { useNavigate } from "react-router-dom";
import "./styles.css";
export default function App() {
const navigate = useNavigate();
return (
<div>
<button onClick={() => navigate("/post-1")}>
Post 1 - Using useNavigate hook
</button>
</div>
);
}
The navigation is done using the useNavigate
hook, So in our test we need to mock the useNavigate
hook and verify it has been called with the exact page route after the button click action.
Component Test
import React from "react";
import { BrowserRouter } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import { screen, render } from "@testing-library/react";
import App from "./App";
// 1- Mocking the hook using jest.fn
const mockedUsedNavigate = jest.fn();
// 2- Mock the library
jest.mock("react-router-dom", () => ({
// 3- Import non-mocked library and use other functionalities and hooks
...(jest.requireActual("react-router-dom") as any),
// 4- Mock the required hook
useNavigate: () => mockedUsedNavigate
}));
describe("App", () => {
it("has a button and does navigate to other component", async () => {
render(
<BrowserRouter>
<App />
</BrowserRouter>
);
// Testing navigating using the button
expect(
screen.getByText("Post 1 - Using useNavigate hook")
).toBeInTheDocument();
await userEvent.click(screen.getByText("Post 1 - Using useNavigate hook"));
expect(mockedUsedNavigate).toHaveBeenCalledWith('/post-1');
});
});
The above test example does the following:
- Create a new mocked function using
jest.fn()
, to be used instead of the actualuseNavigate
hook. - Mocking the whole React-Router-Dom library.
- Import non-mocked React-Router-Dom library and use other functionalities and hooks that are not mocked.
- Replace the actual
useNavigate
implementation with our mocked function created in step1.
At this stage, we’ve mocked the useNavigate
hook from React-Router-Dom, and it’s ready to be tested.
// Testing navigating using the button
expect(
screen.getByText("Post 1 - Using useNavigate hook")
).toBeInTheDocument();
await userEvent.click(screen.getByText("Post 1 - Using useNavigate hook"));
expect(mockedUsedNavigate).toHaveBeenCalledWith('/post-1');
In the above test suite, we’ve verified that the button is existing in the DOM.
Then, we’ve simulated the user click on the button by calling userEvent.click function from React-Testing-Library on the button.
At the last step, we’ve verified that the mockedUsedNavigate
function is being called the exact route /post-1
.
By running the test, we should receive the following results:

Photo from Unsplash
1.can you write a test for useActionData where the action is passed in routes?
2.can you write one where the same action will return different data?
Sure, I’ll put some examples around that soon.