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);
});
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);
});
In this example:
- The
render
function from RTL is used to render theButton
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 theonClick
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
-
jest
is the test runner and framework. -
@testing-library/react
provides utilities for testing React components. -
@testing-library/jest-dom
adds additional matchers liketoBeInTheDocument
,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
4. Writing Tests for React Components
Writing tests for React components with Jest and RTL typically involves the following steps:
-
Render the component: Using RTL’s
render
function to render the component in a virtual DOM. -
Query elements: Use queries like
getByText
,getByRole
, etc., to interact with elements in the rendered component. -
Simulate events: Simulate user interactions (like clicks, form submissions) using
fireEvent
oruser-event
. -
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();
});
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');
});
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();
});
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)