Unit Testing of React Apps using JEST : Tutorial

July 2024 · 9 minute read

Testing software is as important as developing it, since, testing helps find out whether the software meets the actual requirements or not. A thoroughly tested software product ensures dependability, security, and high performance, which leads to time-saving, customer satisfaction, and cost-effectiveness.

ReactJS is a popular JavaScript library that is used for building highly rich user interfaces. Its popularity can be gauged from the significant increase in the number of downloads over the years as seen below.

Most popular JS frameworks

A few reasons that make React a popular framework among developers are:

This tutorial deep dives into performing unit testing of React Apps using JEST.

Table of Contents

What is Unit Testing for React Apps? Why is it important?

Unit Testing is a testing method that tests an individual unit of software in isolation. Unit testing for React Apps means testing an individual React Component.

“Unit testing is a great discipline, which can lead to 40% – 80% reductions in bug density.” – Eric Elliotte

Unit Testing is important for React Apps, as it helps in testing the individual functionality of React components. Moreover, any error in code can be identified at the beginning itself, saving time to rectify it at later stages. Some of the core benefits of Unit Testing are:

How to perform Unit testing of React Apps using JEST?

Jest is a JavaScript testing framework that allows developers to run tests on JavaScript and TypeScript code and can be easily integrated with React JS.

Step 1: Create a new react app

For unit testing a react app, let’s create one using the command given below:

npx create-react-app react-testing-tutorial

Open the package.json, and you will find that when you use create-react-app for creating a react project, it has default support for jest and react testing library. This means that we do not have to install them manually.

Step 2: Create a component

Let’s create a component called Counter, which simply increases and decreases a numeric value at the click of respective buttons.

import React, { useState } from "react"; const Counter = () => { const [counter, setCounter] = useState(0); const incrementCounter = () => { setCounter((prevCounter) => prevCounter + 1); }; const decrementCounter = () => { setCounter((prevCounter) => prevCounter - 1); }; return ( <> <button data-testid="increment" onClick={incrementCounter}> + </button> <p data-testid="counter">{counter}</p> <button disabled data-testid="decrement" onClick={decrementCounter}> - </button> </> ); }; export default Counter;

Here, the important thing to note is the data-testid attributes that will be used to select these elements in the test file.

Step 3: Write a unit test for the react component

Before writing an actual unit test, let’s understand the general structure of a test block:

The unit test of react component can be written as seen in the code snippet below:

import { render, fireEvent, screen } from "@testing-library/react"; import Counter from "../components/Counter"; //test block test("increments counter", () => { // render the component on virtual dom render(<Counter />); //select the elements you want to interact with const counter = screen.getByTestId("counter"); const incrementBtn = screen.getByTestId("increment"); //interact with those elements fireEvent.click(incrementBtn); //assert the expected result expect(counter).toHaveTextContent("1"); });

Note: In order to let jest know about this test file, it’s important to use the extension .test.js.

The above test can be described as:

Step 4: Run the test

Run the test using the following command:

npm run test

Test Result

Test Result of Unit Testing of React Apps

Mocking Data with Jest

Let’s create a component and fetch some data using Axios. For that first install Axios using the following command:

npm i axios

Create a new component inside the components folder as given below:

import React, { useState, useEffect } from "react"; import axios from "axios"; const Todos = () => { const [todoList, setTodoList] = useState(null); useEffect(() => { (async () => { const todos = await axios.get( "https://jsonplaceholder.typicode.com/todos" ); setTodoList(todos.data); })(); }, []); return todoList ? ( <ul> {todoList.map((todo, index) => ( <li key={index} data-testid=’todo’>{todo.title}</li> ))} </ul> ) : ( <p>Loading....</p> ); }; export default Todos;

The above component is simply rendering a list of todos on the browser. Now in order to test this component, one approach can be that the test function itself makes a call to the endpoint of the API and then tests whether the result obtained is correct or not.

But there are a couple of issues with this approach:

So the solution to all the above problems is mocking. The purpose of mocking is to isolate the code tested from external dependencies such as API calls. This is achieved by replacing dependencies with controlled objects that simulate those dependencies.

For creating a mock with jest, first import Axios using the following command:

import axios from 'axios'

Then mock it using the below command:

jest.mock('axios')

Then create dummy data that has a similar format to the actual result, and return the mocked value:

const dummyTodos = [ { userId: 1, id: 1, title: "todo 1", completed: false, }, { userId: 1, id: 2, title: "todo 2", completed: false, }, { userId: 1, id: 3, title: "todo 3", completed: false, }, ]; axios.get.mockResolvedValue({ data: dummyTodos});

Here is the complete code in tests/Todos.test.js file:

import { render, waitFor, screen } from "@testing-library/react"; import Todos from "../components/Todos"; import axios from "axios"; jest.mock("axios"); const dummyTodos = [ { userId: 1, id: 1, title: "todo 1", completed: false, }, { userId: 1, id: 2, title: "todo 2", completed: false, }, { userId: 1, id: 3, title: "todo 3", completed: false, }, ]; test("todos list", async () => { axios.get.mockResolvedValue({ data: dummyTodos }); render(<Todos />); const todoList = await waitFor(() => screen.findAllByTestId("todo")); expect(todoList).toHaveLength(3); });

Test Result

After running the test, the result obtained can be seen below:

Mocking Data in a React Unit Test with Jest

Code Coverage using Jest

Code Coverage means determining how much code has been executed while running the test. Generating a code coverage with jest is quite simple. If you are using npm, run the below code to get the code coverage:

npm test -- --coverage

With yarn, run the following command to get the code coverage:

yarn test --coverage

The result will look something like this:

Code Coverage of React Unit Test using Jest

Best practices for testing React Apps with JEST

Conclusion

Unit testing is the easiest way to improve the quality of your React applications since it helps in finding bugs and defects in your code. Moreover, the early discovery of code bugs in the SDLC reduces the overall cost of development because less time is spent on bug fixing in the later stage of the project. This leads to overall customer satisfaction and helps in gaining more trustworthy clients.

Once, the unit testing is done, it is suggested to test the application end to end on real devices and browsers for identifying bottlenecks in the user experience. Using a real device cloud, like BrowserStack, allows you to test on 3000+ browser device combinations, under real user conditions.

BrowserStack is compatible with different automation frameworks like SeleniumCypress, Playwright, Puppeteer, etc. It is also compatible with CI/CD tools like Jenkins, Travis CI, CircleCI, Bamboo, etc. facilitating test automation in Agile Teams to test on real browsers and devices, thus accelerating the software development cycle. It also supports parallel testing, which helps save time by running tests on multiple browsers and devices simultaneously.

Try React App Testing on BrowserStack for Free

ncG1vNJzZmivp6x7o77OsKqeqqOprqS3jZympmeXqralsY6upaKsXamytMDIp55mp5Ziv6atwq1kmqigqHq2v8innmailajB