App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Get Started free
Home Guide React Testing: How to test React components?

React Testing: How to test React components?

By Mohit Joshi, Community Contributor -

Due to React’s unprecedented popularity, dynamic single-page apps (SPAs) are now being developed by companies worldwide. React, often referred to as a framework, is the most popular open-source UI development JavaScript library managed by Facebook and other open-source communities. 

  • React testing ensures the product’s quality and reliability and must be done thoroughly before rolling out the product to the customers. 
  • Moreover, besides creating UI, it offers several features, such as Flux and React Native. With the help of React Native, you can create cross-platform applications using the same codebase. 

A React application combines several components, each serving as a building block of the application and is highly reusable. Introducing reusable components in the JavaScript code has reduced the development time and complexity. 

Why testing React Components is important?

The basic idea behind implementing React testing on your application is to ensure it works as intended. However, the broader idea behind conducting tests on your React application is to make it less prone to errors and deliver a good user experience. Furthermore, applications are typically updated frequently; testing ensures the application doesn’t break and the code is still reliable. 

React Testing Library is a JavaScript testing utility that provides a set of utility functions that allow developers to interact with the components, such as clicking buttons, entering text, and checking for the presence of certain elements.

The library encourages developers to write tests that are more focused on user behavior and less focused on implementation details.

Types of React Tests

Whenever you’re set to perform React testing, it becomes difficult to deal with the prospect and often left puzzled, but it doesn’t have to be when you have the right tests in your kit. Knowing the different types of tests unlocks the power of testing and helps you deliver better code to ensure your application is reliable, functional, and efficient. 

Three types of tests can be written for React applications

  1. Unit tests: These types of tests are performed to test the functionality of an individual component in isolation.
  2. Integration tests: These tests ensure the proper functioning of different components working together. It tests the interaction between the parent and child components or when the components contain some dependencies.
  3. E2E tests: These tests ensure a proper user experience is received from the user perspective by testing an entire application. 

Three types of tests written for React applications

Setting up the Environment for Testing

Prerequisites

  1. Install the latest version of Node.js on your system. The latest version of React, version 18 requires node.js version 14 or higher. 
  2. Install any IDE of your choice. In this example, we are using Visual Studio Code

Writing Unit Tests for React Components

Unit tests if performed to test an individual component in isolation. The idea behind implementing unit tests for React components is to ensure each component works as intended regarding its design specifications. 

The anatomy of unit tests follows the AAA approach, which stands for

  • Arrange: In this section, as the name suggests, prepare the system for testing. It involves configuring the necessary dependencies and creating required objects. 
  • Act: In this section, you operate on the system that is under test. It may involve calling a function.
  • Assert: In this part, we ensure the outcome matches the expected result. It involves making assertions on the system’s behavior that is under test to ensure its outcome. 

React Testing Components with Jest

Jest is a popular testing framework for React that is simple and powerful enough to write and execute unit tests in React. Jest offers a variety of features for testing React components, such as mocking, snapshot testing, and more.

Now, let’s perform testing of React Components with the help of Jest. In this example, we shall test the ‘HelloWorld’ component which contains the text ‘helloworld’.

Step 1: Install Jest

npm install --save-dev jest

Step 2: Write a Test

Create a .test.js file and paste the following test script inside the file. Write the test with the ‘it’ or ‘test’ function offered by the Jest library. 

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

test('renders a message', () => {
const { getByText } = render(<MyComponent message="Hello, World!" />);
const messageElement = getByText(/Hello, World!/i);
expect(messageElement).toBeInTheDocument();
});

Step 3: Execute the Test

To execute the test, run the following command in the terminal. In this test case, we tested if our application contains the ‘helloworld’ text. 

npx jest HelloWorld.test.js

terminal image 1

Snapshot Testing

Snapshot testing is generally performed for the testing purposes of the user interface. While running the Snapshot test, Jest creates a series of components compared with the previously saved snapshot. If the snapshot matches the previous one, the test passes otherwise, the test fails. 

First Install the latest version of React test renderer with the following command:

npm install react-test-renderer

Let’s write a Snapshot test for the previous test. 

import React from 'react';
import renderer from 'react-test-renderer';
import HelloWorld from './HelloWorld';

test('renders correctly', () => {
const component = renderer.create(<HelloWorld />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

Snapshot testMocking Dependencies 

Mocking dependencies is the procedure followed to ensure the system under test is isolated from external dependencies or interaction with other modules by replacing the module’s implementation or a function with the mock implementation we define. 

Let’s consider a practical example of how to mock dependencies in Jest

const fetchUser = async (userId) => { 
const response = await fetch(`https://api.example.com/users/${userId}`); const data = await response.json(); 
return data; };

const fetch = require('node-fetch');

jest.mock('node-fetch');

describe('fetchUser', () => {

it('returns the user data', async () => {

const mockResponse = { name: 'example' };

fetch.mockResolvedValueOnce({

json: jest.fn().mockResolvedValueOnce(mockResponse),

});

const result = await fetchUser(123);

expect(fetch).toHaveBeenCalledTimes(1);

expect(fetch).toHaveBeenCalledWith('https://api.example.com/users/example');

expect(result).toEqual(mockResponse); 
});

});
  • In this example, jest.mock() is used to mock the node-fetch module. 
  • Then, in the test, fetch.mockResolvedValueOnce() is used to create a mock answer for the fetch() call inside of fetchUser().

Best Practices for Writing Unit Tests

Let’s discuss some of the Unit Testing best practices that must follow to ensure higher reliability, functionality, and efficiency of your unit tests. 

  1. Unit tests are conducted solely to test the individual component without the interference of any other component. Therefore, each component that you put under unit tests must be independent and not rely on any other component or have any dependency. 
  2. To keep the unit test focussed, you must test one thing at a time and should test a specific behavior of a component.
  3. You must invest some time in writing the test names to identify and fix issues if the test fails. You should use descriptive names that specify what you’re testing in a component and what should be the expected outcome. 
  4. Make use of CI/CD pipelines to automate your tests, ensuring the software is always working.

Writing Integration Tests for React Components

In integration testing, the aim is to verify that different system components can work together correctly. To put it another way, an integration test is performed to evaluate how well various components interact. 

The anatomy of an integration test involves four parts, setup, test, assertion, and teardown

  1. Setup: In this part, we set up the environment for the system that is to be tested. This may involve configuring dependencies, components, and load data to ensure they are ready for smooth testing. 
  2. Test: This is the part where the integration test is performed. This may include calling out multiple functions in a test file to verify the behavior of components working in combination. 
  3. Assertion: We ensure the outcome matches the expected result in this part. It involves making assertions on the system’s behavior under different conditions to ensure the expected outcome.
  4. Teardown: In this part, we eliminate the resources used solely for testing purposes. It may involve deleting temporary data or shutting down the unnecessary components required during the testing. 

React Testing with Enzyme

Enzyme is a JavaScript testing library for React that offers a variety of tools for testing React components. Let’s install Enzyme and understand how to perform integration testing with the help of Enzyme. 

Step 1: Install Enzyme and Enzyme adapter

npm install --save-dev @cfaester/enzyme-adapter-react-18

Step 2: Import Enzyme and configure Enzyme adapter

import Enzyme from 'enzyme';
import Adapter from '@cfaester/enzyme-adapter-react-18';

Enzyme.configure({ adapter: new Adapter() });

Shallow Rendering

Shallow rendering is a process of performing React testing in complete isolation without interfering with any of its child components. It is quicker than full rendering, which renders the entire component tree. 

In this example, we’re using Enzyme’s shallow() function to render the HelloWorld component and then using Enzyme’s find() function to locate the <p> element within the component and check its text content.

Create a test file and continue with the following script. 

import React from 'react'; 
import Enzyme, { shallow } from 'enzyme'; 
import Adapter from '@wojtekmaj/enzyme-adapter-react-18'; 
import HelloWorld from './HelloWorld';

Enzyme.configure({ adapter: new Adapter() });

describe('HelloWorld', () => { 
it('renders correctly', () => { 
const wrapper = shallow(<MyComponent />); 
expect(wrapper.find('p').text()).toEqual('Hello, world!'); 
}); 
});

Mounting and Full Rendering

Mounting and Full Rendering is a process of rendering an entire component in a test, including its child components into the DOM. In Full Rendering, the actual rendering of child components occurs whereas, in Mounting only initialization happens. 

Let’s consider a similar practical example to understand Mounting and Full Rendering while testing React components. 

import React from 'react';
import Enzyme, { mount, render } from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-18';
import HelloWorld from './HelloWorld';

Enzyme.configure({ adapter: new Adapter() });

describe(‘HelloWorld', () => {
it('mounts correctly', () => {
const wrapper = mount(<HelloWorld />);
// test component behavior
expect(wrapper.find('button').text()).toEqual('Click me');
});

it('renders correctly', () => {
const wrapper = render(<HelloWorld />);
// test component output
expect(wrapper.find('button').text()).toEqual('Click me');
});
});

Snapshot Testing

Let’s perform Snapshot testing with the help of Enzyme. 

import React from 'react';
import { shallow } from 'enzyme';
import HelloWorld from './HelloWorld';

describe('HelloWorld', () => {
it('should render correctly', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper).toMatchSnapshot();
});
});

Best Practices for Writing Integration Tests

Let’s discuss some of the best practices that must follow to ensure higher reliability, functionality, and efficiency of your integration tests. 

  1. Integration tests can be very time-consuming, therefore, it is a good practice to automate the testing process to save time and prevent any slight human error. 
  2. You must fabricate proper documentation of your Integration tests to ensure they are repeatable and easy to grasp. Documentation is also a necessary aspect as it helps gradually upgrade the overall quality of tests. 
  3. The entire idea behind implementing Integration tests is to ensure the proper functioning of interaction among different components. Therefore, you must test the system as a whole.
  4. Try to incorporate data that reflects upon real-world scenarios for finding out the product’s best and worst use cases.

Writing End-to-End Tests for React Components

End-to-end testing, often known as E2E testing, involves testing an application’s complete lifecycle, including all of its levels and components. In E2E testing we expect the software to work as intended while putting it under real-world scenarios. 

The anatomy of E2E testing for React components includes:

  1. Identifying test scenarios: In this step, test scenarios are identified based on the application’s requirements. 
  2. Set up the test environment: The testing environment should be similar to the production environment, to replicate the real-world scenarios as closely as possible. It involves having the same configurations on the testing and production end. 
  3. Write test scripts: Various testing frameworks are available to run automated test scripts simulating real user interactions with the application. 
  4. Execute the test scripts: Automated test scripts must be executed in a suitable testing environment to ensure higher reliability of tests. 
  5. Analyze the test results: This part involves generating reports on how to test went to identify various issues and defects in the application. 

React Testing with Cypress

Cypress is an end-to-end testing framework based on Node.Js that supports JavaScript/TypeScript as the programming language. Cypress is popular for its ease while performing web application testing. 

Now, let’s consider the practical implementation of Cypress while testing React components. 

Step 1: Installing Cypress

You can use any IDE of your choice for performing testing using Cypress. In this example, we are using Visual Studio IDE. 

To install Cypress, follow the command in the terminal. 

npm install cypress --save-dev

After installing Cypress, open the package.json file and paste the following script inside the script tag.

package.json file

Now run the command to open the Cypress. 

npx run test

Step 2: Create a test file

To create a test file, create a new file with the extension .spec.js in the project directory, cypress/integration

Making Assertions and Interacting with React Components

For example, visit a demo website and click a button that adds the item to a shopping cart. Let’s write a test that verifies that the item is added to the cart after the button is clicked. 

Here is how you may carry out it using Cypress assertions:

// Navigate to the page with the shopping cart button
cy.visit('https://bstackdemo.com/')

// Click the shopping cart button
cy.get('#2').click()

// Assert that the item was added to the cart
cy.get('#cart-items')
.should('contain', 'iPhone12')
.should('contain', '$799')
.should('contain', '1')

Conclusion

The software development process includes React testing as a crucial step. This detailed tutorial demonstrated how to perform React testing using a variety of libraries, including Jest, Enzyme, and Cypress. These frameworks crucially aid unit tests, integration tests, and E2E testing of React components. 

  • No matter which React testing library is chosen, it is essential to test under real user conditions.
  • BrowserStack’s Real Device Cloud allows you to run tests on 3000+ real devices and browsers for real user condition testing.
  • Testing your React application before releasing it to real-world users has several advantages, including ensuring that all users have a positive experience with it.

Start Testing

Tags
Automated UI Testing Automation Testing

Featured Articles

Top Testing Libraries for React in 2023

Top 5 React Native UI Components in 2023

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack