Page cover
Tests aren't overhead - they're confidence. Write tests that matter, catch bugs early, ship fearlessly.

How to Write Unit Tests with Jest and React Testing Library

Testing Intermediate 40-50 minutes December 8, 2024

Master the art of testing React components with Jest and React Testing Library for reliable, maintainable test suites.

Things You'll Need

  • React project set up
  • Basic knowledge of React components
  • Node.js and npm installed

Steps

Follow these 8 steps to complete this guide

1

Install Testing Dependencies

Set up Jest and React Testing Library in your project.

bash
# Install Jest and React Testing Library
npm install -D @testing-library/react @testing-library/jest-dom
npm install -D @testing-library/user-event jest-environment-jsdom

# Install Jest (if not already included)
npm install -D jest
2

Configure Jest

Create a Jest configuration file to set up the testing environment for React.

javascript
// jest.config.js
export default {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  moduleNameMapper: {
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
  },
};
3

Create Setup File

Set up Jest DOM matchers for better assertions.

javascript
// jest.setup.js
import '@testing-library/jest-dom';
4

Write Your First Test

Create a simple test for a React component. Follow the Arrange-Act-Assert pattern.

typescript
// Button.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';

describe('Button', () => {
  it('renders with the correct label', () => {
    // Arrange
    render(<Button label="Click me" onClick={() => {}} />);

    // Assert
    expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
  });

  it('calls onClick when clicked', async () => {
    // Arrange
    const handleClick = jest.fn();
    const user = userEvent.setup();
    render(<Button label="Click me" onClick={handleClick} />);

    // Act
    await user.click(screen.getByRole('button'));

    // Assert
    expect(handleClick).toHaveBeenCalledTimes(1);
  });
});

Tips

  • Use describe blocks to group related tests
  • Use screen.getByRole for more accessible queries
  • userEvent is more realistic than fireEvent
5

Test Component State

Learn how to test components that manage state.

typescript
// Counter.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from './Counter';

describe('Counter', () => {
  it('increments count when button is clicked', async () => {
    const user = userEvent.setup();
    render(<Counter />);

    const button = screen.getByRole('button', { name: /increment/i });
    const count = screen.getByText(/count: 0/i);

    await user.click(button);

    expect(screen.getByText(/count: 1/i)).toBeInTheDocument();
  });
});
6

Test Async Operations

Use findBy queries and waitFor for testing asynchronous behavior.

typescript
// UserList.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import { UserList } from './UserList';

describe('UserList', () => {
  it('displays users after loading', async () => {
    render(<UserList />);

    // Check loading state
    expect(screen.getByText(/loading/i)).toBeInTheDocument();

    // Wait for users to appear
    const user = await screen.findByText(/john doe/i);
    expect(user).toBeInTheDocument();

    // Loading should be gone
    expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
  });
});

Tips

  • Use findBy for elements that will appear async
  • Use waitFor when you need to wait for an assertion
  • Mock API calls to avoid network requests in tests
7

Mock API Calls

Mock fetch or axios calls to test components in isolation.

typescript
// UserList.test.tsx
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve([
      { id: 1, name: 'John Doe' },
      { id: 2, name: 'Jane Smith' }
    ]),
  })
) as jest.Mock;

describe('UserList', () => {
  beforeEach(() => {
    (fetch as jest.Mock).mockClear();
  });

  it('fetches and displays users', async () => {
    render(<UserList />);

    await waitFor(() => {
      expect(screen.getByText(/john doe/i)).toBeInTheDocument();
    });

    expect(fetch).toHaveBeenCalledTimes(1);
  });
});
8

Run Your Tests

Execute your test suite and view the results.

bash
# Run all tests
npm test

# Run tests in watch mode
npm test -- --watch

# Run tests with coverage
npm test -- --coverage

Tips

  • Aim for at least 80% code coverage
  • Watch mode is great for TDD (Test-Driven Development)
  • Use coverage reports to find untested code
Tags: React Jest Testing Testing Library

Was this guide helpful?

Check out more step-by-step guides for development, deployment, debugging, and configuration.