DEV Community

Abhay Singh Kathayat
Abhay Singh Kathayat

Posted on

Mastering Testing in React with Jest and React Testing Library

Testing with Jest and React Testing Library

Testing is a crucial aspect of building reliable and maintainable applications. For React applications, Jest and React Testing Library (RTL) are the most commonly used tools to test components, functionality, and behavior.

In this article, we’ll explore how to use Jest and React Testing Library for testing React applications.


1. Jest Overview

Jest is a JavaScript testing framework developed by Facebook. It’s widely used for testing React applications, and it’s the default testing library created for React by the React team.

Key Features of Jest:

  • Zero configuration: Jest requires minimal setup to get started.
  • Snapshot testing: It allows you to compare your rendered output to a stored snapshot and detect changes.
  • Mocking: Jest has powerful mocking abilities to mock functions, modules, or APIs.
  • Asynchronous testing: Jest provides methods to handle asynchronous code testing with async/await or Promises.
  • Built-in test runner: Jest runs tests, generates test reports, and handles parallel test execution.

Example Test with Jest:

// sum.js
export const sum = (a, b) => a + b;

// sum.test.js
import { sum } from './sum';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
Enter fullscreen mode Exit fullscreen mode

In this simple test, Jest checks if the sum of 1 and 2 equals 3.


2. React Testing Library (RTL) Overview

React Testing Library is a testing utility for testing React components in a way that simulates user behavior. It encourages writing tests based on how the components are used, rather than focusing on their internal implementation details.

Key Features of React Testing Library:

  • User-centric testing: Encourages testing from the user’s perspective, focusing on what’s displayed on the screen.
  • No implementation details: RTL avoids testing internal component logic and focuses on testing how components behave in the UI.
  • Queries for elements: Provides utility functions to find elements based on user-centric queries like getByText, getByRole, etc.
  • Works well with Jest: RTL is usually used with Jest to run tests, check assertions, and generate test reports.

Example Test with React Testing Library:

// Button.js
import React from 'react';

const Button = ({ onClick, label }) => (
  <button onClick={onClick}>{label}</button>
);

export default Button;

// Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('Button displays correct label and handles click', () => {
  const handleClick = jest.fn();

  render(<Button label="Click Me" onClick={handleClick} />);

  const buttonElement = screen.getByText('Click Me');
  expect(buttonElement).toBeInTheDocument();

  fireEvent.click(buttonElement);
  expect(handleClick).toHaveBeenCalledTimes(1);
});
Enter fullscreen mode Exit fullscreen mode

In this example:

  • The render function from RTL is used to render the Button component.
  • The screen.getByText is used to find the button by its label.
  • The fireEvent.click simulates a user clicking the button.
  • The Jest mock function jest.fn() tracks the call to the onClick handler.

3. Setting Up Jest and React Testing Library

To get started, you need to install Jest and React Testing Library into your React project.

Install Jest and RTL:

npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Enter fullscreen mode Exit fullscreen mode
  • jest is the test runner and framework.
  • @testing-library/react provides utilities for testing React components.
  • @testing-library/jest-dom adds additional matchers like toBeInTheDocument, toHaveTextContent, etc., for improved assertions.

Jest comes with built-in configurations, so no additional setup is needed in most cases.

Example of Running Tests:

# Run all tests
npm test

# Run tests in watch mode
npm test -- --watch
Enter fullscreen mode Exit fullscreen mode

4. Writing Tests for React Components

Writing tests for React components with Jest and RTL typically involves the following steps:

  1. Render the component: Using RTL’s render function to render the component in a virtual DOM.
  2. Query elements: Use queries like getByText, getByRole, etc., to interact with elements in the rendered component.
  3. Simulate events: Simulate user interactions (like clicks, form submissions) using fireEvent or user-event.
  4. Assertions: Use Jest’s expect and various matchers to assert that the component behaves as expected.

Commonly Used Queries in React Testing Library:

  • getByText: Finds elements by their visible text content.
  • getByRole: Finds elements by their role (e.g., button, heading).
  • getByLabelText: Finds form elements associated with labels.
  • getByPlaceholderText: Finds input elements by their placeholder text.

Example of a Test with Multiple Queries:

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

test('should submit form with correct values', () => {
  render(<Form />);

  // Access form elements
  const inputName = screen.getByLabelText(/name/i);
  const inputEmail = screen.getByLabelText(/email/i);
  const submitButton = screen.getByRole('button', { name: /submit/i });

  // Simulate user input
  fireEvent.change(inputName, { target: { value: 'John Doe' } });
  fireEvent.change(inputEmail, { target: { value: 'john@example.com' } });

  // Simulate form submission
  fireEvent.click(submitButton);

  // Assert form submission
  expect(screen.getByText(/form submitted successfully/i)).toBeInTheDocument();
});
Enter fullscreen mode Exit fullscreen mode

5. Mocking with Jest

Jest provides powerful mocking utilities to mock functions, modules, and APIs. This is useful when testing components that rely on external data or functions.

Example of Mocking a Function:

// fetchData.js
export const fetchData = async () => {
  const response = await fetch('/api/data');
  return response.json();
};

// fetchData.test.js
import { fetchData } from './fetchData';

jest.mock('./fetchData');

test('fetchData should return mocked data', async () => {
  fetchData.mockResolvedValue({ data: 'test' });

  const result = await fetchData();
  expect(result.data).toBe('test');
});
Enter fullscreen mode Exit fullscreen mode

6. Snapshot Testing

Snapshot testing allows you to store the rendered output of a component and compare it with future renderings to catch any unintended changes.

Example of Snapshot Testing:

import { render } from '@testing-library/react';
import Button from './Button';

test('Button renders correctly', () => {
  const { asFragment } = render(<Button label="Click Me" />);

  // Snapshot test
  expect(asFragment()).toMatchSnapshot();
});
Enter fullscreen mode Exit fullscreen mode

This will create a snapshot file, and in subsequent test runs, Jest will compare the rendered output against the saved snapshot.


Conclusion

Testing React components with Jest and React Testing Library ensures that your application works as expected and helps in catching regressions early. Here's a recap:

  • Jest is a JavaScript testing framework that provides utilities for assertions, mocks, and running tests.
  • React Testing Library allows you to test React components with a focus on how the user interacts with the UI.
  • By combining Jest and RTL, you can write comprehensive tests for your components, validate their behavior, and ensure the quality of your codebase.

Top comments (0)