How to Test React Router Outlet Component

Testing the <Outlet /> component in React Router is essential for ensuring that nested routes render their child components correctly. This article provides a straightforward, step-by-step guide on how to test React Router’s Outlet component using React Testing Library and Jest, covering both integration testing with MemoryRouter and mock-based unit testing.

The most reliable way to test a component containing an <Outlet /> is through an integration test. By using MemoryRouter (or createMemoryRouter), you can simulate actual routing behavior and verify that the correct child components render inside the parent layout.

The Component to Test

Consider a layout component that uses Outlet to render nested child components:

// DashboardLayout.jsx
import { Outlet, Link } from 'react-router-dom';

export default function DashboardLayout() {
  return (
    <div>
      <nav>
        <Link to="/dashboard/profile">Profile</Link>
      </nav>
      <header>
        <h1>Dashboard Header</h1>
      </header>
      <main>
        <Outlet />
      </main>
    </div>
  );
}

The Test File

Use createMemoryRouter to define a mock routing tree. This allows you to test what renders inside the Outlet when navigating to specific paths.

// DashboardLayout.test.jsx
import { render, screen } from '@testing-library/react';
import { RouterProvider, createMemoryRouter } from 'react-router-dom';
import DashboardLayout from './DashboardLayout';

describe('DashboardLayout Component', () => {
  test('renders the layout and the nested outlet route component', () => {
    const routes = [
      {
        path: '/dashboard',
        element: <DashboardLayout />,
        children: [
          {
            path: 'profile',
            element: <div>Profile Page Content</div>,
          },
        ],
      },
    ];

    // Start the router at the specific child path
    const router = createMemoryRouter(routes, {
      initialEntries: ['/dashboard/profile'],
    });

    render(<RouterProvider router={router} />);

    // Assert that the layout elements are rendered
    expect(screen.getByText('Dashboard Header')).toBeInTheDocument();

    // Assert that the child component inside the Outlet is rendered
    expect(screen.getByText('Profile Page Content')).toBeInTheDocument();
  });
});

Method 2: Mocking the Outlet Component (Isolated Unit Test)

If you only want to verify that the parent layout contains the Outlet component without testing the routing logic, you can mock react-router-dom using Jest.

The Test File

In this approach, you replace the real Outlet with a placeholder test ID to confirm its presence in the DOM.

// DashboardLayout.isolated.test.jsx
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import DashboardLayout from './DashboardLayout';

// Mock react-router-dom to stub out the Outlet component
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  Outlet: () => <div data-testid="mock-outlet" />,
}));

describe('DashboardLayout Isolated Unit Test', () => {
  test('renders the layout and contains the Outlet component placeholder', () => {
    render(
      <MemoryRouter>
        <DashboardLayout />
      </MemoryRouter>
    );

    // Verify layout header is present
    expect(screen.getByText('Dashboard Header')).toBeInTheDocument();

    // Verify the mocked Outlet is rendered inside the layout
    expect(screen.getByTestId('mock-outlet')).toBeInTheDocument();
  });
});