How to Mock Link Component in React

Testing React components often requires isolating them from external dependencies like routing. This article provides a straightforward guide on how to mock the Link component from popular routing libraries like React Router and Next.js using Jest and React Testing Library, allowing your unit tests to run smoothly without routing context errors.

When testing a component that contains a Link component, you will often encounter errors. This happens because the Link component expects to exist within a router context (like BrowserRouter or Next.js Router). Mocking the Link component allows you to bypass the need for this provider wrapper, simplifying your test setup and focusing purely on the component’s behavior.

If your project uses React Router, you can mock the Link component globally or within a specific test file using jest.mock. The best approach is to replace it with a standard HTML anchor (<a>) tag.

Here is how you can do it:

import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';

// Mock the react-router-dom Link component
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  Link: ({ children, to }) => <a href={to}>{children}</a>,
}));

describe('MyComponent', () => {
  it('renders the mocked link correctly', () => {
    render(<MyComponent />);
    
    const linkElement = screen.getByRole('link', { name: /home/i });
    expect(linkElement).toBeInTheDocument();
    expect(linkElement).toHaveAttribute('href', '/home');
  });
});

Using jest.requireActual ensures that you only mock the Link component while keeping other exports from react-router-dom intact.

Next.js projects use next/link for routing. You can mock this component in a similar way by converting it into a simple anchor tag.

import React from 'react';
import { render, screen } from '@testing-library/react';
import Navigation from './Navigation';

// Mock the next/link component
jest.mock('next/link', () => {
  return ({ children, href }) => {
    return <a href={href}>{children}</a>;
  };
});

describe('Navigation Component', () => {
  it('renders the Next.js mock link', () => {
    render(<Navigation />);
    
    const linkElement = screen.getByRole('link', { name: /about/i });
    expect(linkElement).toBeInTheDocument();
    expect(linkElement).toHaveAttribute('href', '/about');
  });
});

Alternative: Wrapping with a Router Provider

If you prefer not to mock the Link component, you can wrap your component in a memory router during render. This is useful when you want to test actual navigation logic.

For React Router, use MemoryRouter:

import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import MyComponent from './MyComponent';

test('renders link inside MemoryRouter', () => {
  render(
    <MemoryRouter>
      <MyComponent />
    </MemoryRouter>
  );
});