How to Test React Error Boundaries

Testing Error Boundaries in React ensures your application gracefully handles runtime crashes and displays a fallback UI to users instead of a blank screen. This article provides a straightforward guide on how to test React Error Boundaries using Jest and React Testing Library, demonstrating how to simulate component errors, assert correct fallback rendering, and suppress noisy console error logs during your test runs.

The Testing Strategy

To test an Error Boundary, you must force a child component to throw an error during its render phase. Your test should then verify that: 1. The crash is intercepted by the Error Boundary. 2. The designed fallback UI (such as an error message or a redirect button) renders successfully. 3. The rest of the application does not crash.

Step-by-Step Implementation

Below is a complete example of how to test a standard React Error Boundary using Jest and React Testing Library.

1. Create a Problematic Component

First, create a dummy component that intentionally throws an error when rendered. This will act as the trigger for your Error Boundary.

const ProblemChild = () => {
  throw new Error('Test Error');
};

2. Write the Test Case

Wrap the ProblemChild component inside your ErrorBoundary component within the render function of React Testing Library.

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

// A component that intentionally throws an error
const ProblemChild = () => {
  throw new Error('Test Error');
};

describe('ErrorBoundary Component', () => {
  // Suppress console.error logging for clean test output
  beforeEach(() => {
    jest.spyOn(console, 'error').mockImplementation(() => {});
  });

  afterEach(() => {
    console.error.mockRestore();
  });

  test('should render fallback UI when a child component throws an error', () => {
    render(
      <ErrorBoundary fallback={<div>Something went wrong.</div>}>
        <ProblemChild />
      </ErrorBoundary>
    );

    // Assert that the fallback UI is rendered
    const fallbackMessage = screen.getByText('Something went wrong.');
    expect(fallbackMessage).toBeInTheDocument();
  });

  test('should render children when there is no error', () => {
    render(
      <ErrorBoundary fallback={<div>Something went wrong.</div>}>
        <div>Normal Child Component</div>
      </ErrorBoundary>
    );

    // Assert that the normal UI is rendered
    const normalChild = screen.getByText('Normal Child Component');
    expect(normalChild).toBeInTheDocument();
  });
});

Key Considerations when Testing Error Boundaries

Suppressing Console Errors

React automatically logs caught errors to the console, which can make your test suite output look like it failed even when the tests pass. Using jest.spyOn(console, 'error').mockImplementation(() => {}) suppresses these logs during the test run. Remember to restore the original console behavior in afterEach to avoid hiding actual errors in other tests.

Testing Error Logging Handlers

If your Error Boundary sends error logs to an external service (like Sentry or LogRocket) via componentDidCatch, you should mock that logging function and assert that it was called with the correct error parameters:

expect(logService.logError).toHaveBeenCalledWith(expect.any(Error));