How to Mock NavLink in React
Testing React components that use NavLink from
react-router-dom often causes errors because the component
expects to be rendered within a router context. This article explains
how to resolve this issue using two different approaches: wrapping your
component with MemoryRouter for integration tests, or
mocking the react-router-dom library directly using Jest
for unit tests.
Method 1: Wrapping with MemoryRouter (Recommended)
The easiest and most reliable way to test components with
NavLink is to wrap them in a MemoryRouter
provided by react-router-dom. This avoids mocking the
component entirely and allows you to test actual navigation
behavior.
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import NavigationMenu from './NavigationMenu';
test('renders NavLink components correctly', () => {
render(
<MemoryRouter initialEntries={['/']}>
<NavigationMenu />
</MemoryRouter>
);
const homeLink = screen.getByRole('link', { name: /home/i });
expect(homeLink).toBeInTheDocument();
expect(homeLink).toHaveAttribute('href', '/home');
});Using MemoryRouter ensures that your tests behave as
closely as possible to the real application production environment.
Method 2: Mocking react-router-dom with Jest
If you want to isolate your component and avoid rendering the actual
router logic, you can mock react-router-dom globally or
inside a specific test file. You can replace NavLink with a
standard HTML anchor (<a>) tag.
Here is how to mock NavLink using Jest:
import { render, screen } from '@testing-library/react';
import NavigationMenu from './NavigationMenu';
// Mock the react-router-dom library
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
NavLink: ({ to, children, className, ...rest }) => (
<a href={to} className={typeof className === 'function' ? className({ isActive: false }) : className} {...rest}>
{children}
}
</a>
),
}));
test('renders the mocked NavLink component', () => {
render(<NavigationMenu />);
const homeLink = screen.getByRole('link', { name: /home/i });
expect(homeLink).toBeInTheDocument();
expect(homeLink).toHaveAttribute('href', '/home');
});Key Details of the Mock:
jest.requireActual: Ensures that other parts ofreact-router-dom(likeRoutesorRoute) still work normally if they are imported elsewhere in your tests.- Functional
className: BecauseNavLinksupports passing a function to theclassNameprop to toggle active styles (e.g.,({ isActive }) => ...), the mock checks ifclassNameis a function and calls it to prevent runtime errors.