Unit Testing 101 With React Testing Library
<  Go to blog home page

Unit Testing 101 With React Testing Library


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.

Explore our next posts

How to Create the Best Senior Software Developer CV [2024]
Technology

How to Create the Best Senior Software Developer CV [2024]

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

How to Integrate Remote Teams Across Cultures: 5 Tips for Success
Management

How to Integrate Remote Teams Across Cultures: 5 Tips for Success

In today’s world of working remotely, the key to integrate remote teams lies in promoting efficient teamwork between professionals from different countries. If you aim to make use of exceptional talent from around the world without any obstacles in multicultural collaboration, it is crucial to consider methods of fostering unity. Achieving success depends on your

Outsourcing Developers to Mexico: A 2024 Guide for Scale-ups
Management

Outsourcing Developers to Mexico: A 2024 Guide for Scale-ups

When it comes to outsourcing software developers, Mexico is widely recognized as a top resource for hiring exceptional talent from Latin America. But what sets Mexico apart? Mexico boasts a thriving technological scene, which includes numerous innovative startups, vibrant developer communities, and high-quality outsourcing partnerships. In short, Mexico is a great choice for software development

Join BEON.tech's community today

Apply for jobs Hire developers