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>
`);
});