React Testing Library: Unit Testing Guide

Frontend development relies heavily on unit testing to verify that different components of the codebase work correctly. This article will delve into the fundamental principles of unit testing in a ReactJS application, with a specific emphasis on using React Testing Library to test components…

Published on Updated on

Verified author
Bruno Feitoza
Written by Bruno Feitoza Senior Software Engineer
Contents

Frontend development relies heavily on unit testing to verify that different components of the codebase work correctly. This article will delve into the fundamental principles of unit testing in a ReactJS application, with a specific emphasis on using React Testing Library to test components, context API, custom hooks, and especially user interactions. Additionally, we will see the potential integration of unit tests within the CI/CD pipeline and underscore the significance of test coverage reporting.

Benefits of unit testing in frontend development 

Unit testing plays a vital role in improving code quality, catching bugs early in the development process, and facilitating a test-driven development approach. With React Testing Library, developers can write tests that closely resemble how users interact with the application, leading to more robust and maintainable code. 

Understanding the React Testing library 

React Testing Library is a popular testing utility for React that encourages testing components in a way that resembles user behavior. When testing React components, it focuses on testing the rendered output rather than implementation details, resulting in tests that are more resilient to changes in the component’s internal structure. 

Choosing tools: Vitest and Jest 

When we are setting up the testing tools for our application, it’s common to think on what tool we will use, Jest or another one? Recently Vitest is getting more and more popular. It’s a testing tool, similar to Jest, built on top of Vite and offering a very attractive alternative to Jest for several reasons.

Vitest prioritizes speed and developer experience, providing faster and more performant unit tests. It seamlessly integrates with the Jest API and ecosystem libraries, enabling a smooth transition for projects already using Jest. Plus it includes some custom functionalities for your test suites. 

Writing tests for Context API and custom hooks 

In modern React applications, Context API and custom hooks play a crucial role in managing state and encapsulating reusable logic. With React Testing Library, we can effectively test components that consume context and hooks by simulating their behavior and testing the resulting output. 

Testing components with Context API 

When testing components that consume a context, it’s essential to create a testing environment that provides the necessary context values. This can be achieved using the Provider component from the relevant context. Look at the example below: 

// Sample test for a component consuming context 

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

import { UserContext, UserProvider } from './UserContext'; 

test('displays username from context', () => { 

 render( 

 <UserProvider value={{ username: 'Bruno' }}> 

 <UserProfile /> 

 </UserProvider> 

 );                                                                                  

 // Assertions to validate the rendering of the username }); 

Testing custom hooks 

For testing custom hooks, it’s important to focus on the behavior and output of the hook under certain conditions. This can be done by invoking the custom hook within the testing environment and asserting the expected behavior. Look at the example below: 

// Sample test for a custom hook 

import { renderHook } from '@testing-library/react-hooks'; import { useCounter } from './useCounter'; 

test('increments counter value', () => { 

const { result } = renderHook(() => useCounter());  result.current.increment(); 

expect(result.current.count).toBe(1);                                                

}); 

It also requires the library @testing-library/react-hooks 

Mocking dependencies and APIs with Vitest

In Vitest, mocking modules and APIs can be achieved using utility functions provided by the vi helper. The vi.mock function substitutes all imported modules from a specified path with another module, enabling the controlled replacement of dependencies for testing purposes. 

// Mocking a module using Vitest 

vi.mock('./path/to/module.js', async (importOriginal) => {  const mod = await importOriginal(); 

 return { 

 ...mod, 

 namedExport: vi.fn(), // Replace the namedExport with a moc  };                     

}); 

Asserting with React Testing library 

As mentioned before, we can do specific assertions using RTL aiming to simulate the user behavior, here are some assertion examples:

// Asserting that a text is rendered in the document 

import React from 'react'; 

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

import MyComponent from './MyComponent'; 

test('renders MyComponent', () => { 

const { getByText } = render(<MyComponent />);  const textElement = getByText('Hello, World!');  expect(textElement).toBeInTheDocument(); 

}); 

// Asserting conditional rendering 

import React from 'react'; 

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

import ConditionalComponent from './ConditionalComponent'; 

test('renders based on condition', () => { 

const { getByText, queryByText } = render(<ConditionalComponen  const visibleTextElement = getByText('Visible Content');  const hiddenTextElement = queryByText('Hidden Content');  expect(visibleTextElement).toBeInTheDocument();  expect(hiddenTextElement).toBeNull(); 

}); 

// Form validations 

import React from 'react'; 

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

test('submits form with valid input', () => { 

const { getByLabelText, getByText } = render(<LoginForm />);  const emailInput = getByLabelText('Email');

const passwordInput = getByLabelText('Password');  const submitButton = getByText('Submit'); 

fireEvent.change(emailInput, { target: { value: 'user@example  fireEvent.change(passwordInput, { target: { value: 'password12  fireEvent.click(submitButton); 

 // Validate the form submission result 

}); 

The importance of CI/CD integration 

While we won’t delve into the specifics of setting up a CI/CD pipeline for testing in this article, it’s important to note that integrating unit tests into the development workflow can significantly improve code quality. 

Additionally, incorporating test coverage reporting into the CI/CD pipeline allows developers to track the percentage of code covered by tests, providing valuable insights into the overall quality of the codebase. 

Key Takeaways

  • Unit testing is an integral part of frontend development, and with the right tools and best practices, developers can ensure the reliability and maintainability of their code. 
  • By leveraging React Testing Library, context API, and custom hooks, developers can write effective unit tests that enhance the overall quality of their React applications. 
  • Integrating unit tests into the CI/CD pipeline and monitoring test coverage can further elevate the development process, ultimately leading to more robust and stable applications.

Building a team that works with these tools? BEON.tech helps US companies hire senior React developers from Latin America who work in your time zone.

Verified author
Bruno Feitoza
Written by Bruno Feitoza Senior Software Engineer

Bruno Feitoza is a Senior Software Engineer from Brazil who has worked with BEON.tech since 2022. He has more than 7 years of experience building web applications with React, Node.js and TypeScript, and holds a postgraduate degree in Software Engineering from FIAP. He writes from hands-on project work: an AI coding-agent workflow from Jira ticket to pull request, migrating 4 million MongoDB documents, testing with React Testing Library, and lessons from working inside US engineering teams.

Expertise
ReactJSNodeJSJava ScriptType Script

Ready to build your team in Latin America?

Let us connect you with pre-vetted senior developers who are ready to make an impact.

Get started

Explore our next posts

Hiring Software Developers

How to Write a Senior Software Developer CV

As you advance in your software development career, your job search priorities undergo a significant transformation. It’s time to move beyond accepting subpar salaries and minimal benefits. The great news is that many companies are adopting a developer-centric approach, recognizing that a competitive salary is just a starting point. However, there’s a catch: to secure…

Ana Chirinos Jan 25, 2024 8 min read
BEON.tech News

BEON.tech Wins 2023 Clutch Global and Champion

We’re proud to announce that BEON.tech has been recognized as a 2023 Clutch Global and Clutch Champion Winner! As a Tech Talent Partner connecting the brightest LATAM talent with elite U.S. companies, we are honored to be ranked among Clutch’s top 10% of companies this fall. The 2023 Fall Clutch Global Award serves as a…

BEON.tech Dec 6, 2023 3 min read
Engineering Management

Ambassadors’ Week 2023 at Our Buenos Aires HQ

In early November 2023, we celebrated our third Ambassadors’ Week edition and are thrilled with all the amazing experiences we had! What’s Ambassadors’ Week, you ask? It’s an annual event where we gather with all our collaborators. During that week, our talented software developers and Talent Experience Managers from across Latin America converged on our…

Belen Rocha Nov 30, 2023 2 min read
Hiring engineers? Talk to an expert. Talk to an expert