Discover the power of React Unit Testing with our comprehensive guide. Ensure robust applications and detect bugs early. Start testing like a pro today!
Unit testing is a critical part of building successful software applications. It ensures that the code being written meets specific requirements, performs as expected, and can be maintained over time. React, released in May 2013, is one of the most popular JavaScript libraries for creating user interfaces in web applications. Jest is the most widely used testing framework for unit testing React components.
This article will explore Jest for writing unit tests for React components. We'll look at what constitutes a unit test, how to write tests using Jest APIs and assertion methods, and some best practices for writing effective unit tests.
Jest was created in 2011 by Facebook and has now become the de facto standard for writing unit tests with React due to its powerful assertion library, comprehensive mocking capabilities, and easy configuration process, among other features. All of these features allow you to write meaningful tests quickly without worrying about configuration details or dealing with complex configuration processes for each tool separately.
To effectively use Jest to write unit tests in React applications, you must first understand how different types of assertions work, what mocking means, and best practices for setting up your environment. This article will provide an overview of all these topics so that readers can gain enough knowledge to write meaningful, yet maintainable unit tests quickly!
Why is React unit testing important?
Unit testing is essential for several reasons, some of which are mentioned below:
Reduced development time
Unit testing can reduce the time spent debugging, preventing bugs from appearing later in the development cycle. By writing unit tests before coding, React developers can quickly identify any issues with their code before diving into implementation.
This allows them to make adjustments or corrections as quickly as possible without starting from scratch if something goes wrong. Additionally, once a unit test suite has been written for an application, it can be run again after any major changes have been made to ensure everything works as expected.
Improved code quality
By running automated unit tests regularly during development, developers can catch errors and inconsistencies early, before they become much bigger problems in the future. Writing comprehensive test cases also encourages better coding practices because it requires programmers to think upfront about what inputs might lead to unexpected results or bugs later in the development process.
As a result, a unit test often leads to better overall code quality and fewer bugs compared to projects that do not employ this testing method or only partially implement it during their workflow.
Better documentation
Programmers who write unit tests help create clear documentation for each part of an application because every step a programmer takes must be completely documented so that other programmers or engineers working with the same software understand exactly what was done and why. was made. way and not otherwise.
Furthermore, good documentation helps future maintenance personnel maintain existing applications more easily, as they will know exactly which functions were used, where specific variables were declared, etc. With proper documentation, understanding complex pieces of software becomes much easier.
Greater reliability and maintainability
Unit tests help ensure reliability because they check for bugs at each level throughout an application's lifecycle. When these checks fail due to new bugs being introduced into an application, developers can resolve them immediately rather than waiting until later to repair damage caused by unnoticed bugs.
This increased level of monitoring also means less time wasted trying to track down sources of various problems, since most have already been detected early through rigorous response unit testing procedures.
Furthermore, maintainability increases significantly when multiple sets of test cases cover different aspects of functionality within the chosen area (e.g. UI logic), meaning that future updates/changes only need to pass established criteria previously; the order remains valid after modifications occur.
What is a joke?
Jest is a JavaScript testing framework created by Facebook. It performs unit and integration testing on applications written in any language that transpiles to JavaScript, including React, Vue, Angular, Node.js, and more. Jest provides a powerful assertion library with built-in code coverage reports and other features that make it easy to start writing tests for your application.
Let's jump into implementing unit tests in React!
How can we implement unit tests in React?
Let's see how we can implement unit tests in a React application.
Prerequisites
To implement unit testing successfully, you must have the following:
- Node.js : The latest version of Node.js on your machine.
- A code editor : Any IDE that supports React.
- Just kidding : A JavaScript testing framework that works well with React.
- React Testing Library : Provides utilities for testing React components.
Starting
Installing and creating a new React application
Run the following command in your terminal to install Create React App . It's a tool that bootstraps a react app without build configuration.
$ npm install create-react-app
Once Create React App is installed, you must run the following command.
$ npx create-react-app my-app
Now navigate to the my-app directory.
$ cd my-app
Run the following command to launch the React app you created.
$ npm start
You will see the output similar to the one below in your terminal: Compiled successfully! You can now view demo in the browser. Local: On Your Network: Note that the development build is not optimized. To create a production build, use npm run build. webpack compiled successfully
When you access the / URL, you will see a default page for your React application.
We need to install Jest and React Testing Library as a development dependency.
Installing Jest using Terminal
Run the following command in your terminal to install Jest.
$ npm install --save-dev jest
Installing the React testing library using terminal
Run the following command in your terminal to install the React Testing Library.
$ npm install --save-dev @testing-library/react
Once all the packages are installed, we will add a script in the package.json file to automatically run the tests whenever called.
This is what package.json looks like now.
Please note the versions of the packages mentioned above as they were used when this guide was created.
Once Jest is installed, we can create a test file in our React application. Jest will automatically select files ending with .test.js or .spec.js in your project directory.
Writing a unit test case
Another important thing to know is how to write a unit test case.
Query type | 0 matches | 1 match | > 1 matches | Retry (async/await) |
Single Element | ||||
getBy... |
Launch error | Return element | Launch error | No |
queryBy... |
Return null | Return element | Launch error | No |
findBy... |
Launch error | Return element | Launch error | Yes |
Various elements | ||||
getAllBy... |
Launch error | Return matrix | Return matrix | No |
queryAllBy... |
Turn back | Return matrix | Return matrix | No |
findAllBy... |
Launch error | Return matrix | Return matrix | Yes |
Source: Testing library documentation
Resuming:
- You must use getBy, findBy, or queryBy when selecting a single DOM element.
- You must use getAllBy, findAllBy, or queryAllBy when selecting multiple DOM elements.
- When there is more than one or no match, the getBy and findBy queries return an Error.
- When there is no match, a null value is returned; otherwise, if there is more than one match, an error is returned by queryBy
- getBy and queryBy don't work well with asynchronous code, while findBy does.
- If there are any matches, an array of matches will be returned, otherwise an error will be given by the getAllBy query.
- If there are any matches, an array of matches will be returned, otherwise an error will be given by the findAllBy query.
- If there are any matches, an array of matches is returned; otherwise, an empty array will be returned by the getAllBy query.
Now that you are familiar with query methods, let's start writing a unit test case for the React component.
Let's create a component first. Create a new file with the component name. In our case, we will make MyComponent.js in src with the following:
export default function MyComponent { return <div>Hello, World</div>; }
Now add the component in the App.js file so that
import logo from './logo.svg'; import './App.css'; import MyComponent from './MyComponent'; function App { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> React App Demo. </p> <MyComponent /> </header> </div> ); } export defaultApp;
Let's create a simple test file to test a React component:
// MyComponent.test.js import React from 'react'; import { render } from '@testing-library/react'; import MyComponent from './MyComponent'; describe('MyComponent', => { it('renders correctly', => { const { getByText } = render(<MyComponent />); const linkElement = getByText(/Hello World/i); expect(linkElement).toBeInTheDocument; }); });
In the example shown, we import the rendering resource from @testing-library/react for use in a testing environment.
Next, we place our MyComponent in scope and apply the render function to it. Finally, with getByText, we can retrieve the text “Hello World” and check its presence using expect .
To run this test, type the following command in the terminal window:
$ npm test
The output should be as follows:
If you change the content of the div and run the test. The output in the terminal will be:
The describe function is used to group our tests and its function defines a specific test. The expect function is used to make assertions about the output of our code.
Testing props and state
In React, components can have props and states. It is essential to test that these values are being set and updated correctly. Let's update our MyComponent example to test a property:
// MyComponent.test.js import React from 'react'; import { render } from '@testing-library/react'; import MyComponent from './MyComponent'; describe('MyComponent', => { it('renders correctly', => { const { getByText } = render(<MyComponent />); const linkElement = getByText(/Hello World/i); expect(linkElement).toBeInTheDocument; }); it('renders the correct name prop', => { const { getByText } = render(<MyComponent name="Alice" />); const linkElement = getByText(/Hello Alice/i); expect(linkElement).toBeInTheDocument; }); });
In the example above, we are testing whether the component renders the correct name prop. We pass the property to the component when we render it using the render method. We then use the getByText method to retrieve the text “Hello Baires” and check if it is in the document using the expect method.
The test state is similar to the props test. We can use the fireEvent method from @testing-library/react to simulate user interactions with the component:
// MyComponent.test.js import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import MyComponent from './MyComponent'; describe('MyComponent', => { it('renders correctly', => { const { getByText } = render(<MyComponent />); const linkElement = getByText(/Hello World/i); expect(linkElement).toBeInTheDocument; }); it('renders the correct name prop', => { const { getByText } = render(<MyComponent name="Alice" />); const linkElement = getByText(/Hello Baires/i); expect(linkElement).toBeInTheDocument; }); it('updates the count state on button click', => { const { getByText, getByTestId } = render(<MyComponent />); const countElement = getByTestId('count'); const buttonElement = getByText(/Click me/i); expect(countElement).toHaveTextContent('0'); fireEvent.click(buttonElement); expect(countElement).toHaveTextContent('1'); }); });
In the example above, we are testing whether the count state is updated when the user clicks the “Click me” button. We use the getByTestId method to retrieve the count element and the getByText method to retrieve the button element.
We then use the expect method to check whether the count element initially has the value 0, we simulate a click event using the fireEvent method and check whether the count element has the value 1.
Why is Jest a great option for unit testing in React?
Here is a comparison of some popular testing frameworks.
Structure | Test type | Language | DOM Test | Code coverage | Snapshot Test | Active Community |
Joke | Unit | JavaScript | Yes | Yes | Yes | Yes |
Mocha | Unity and Integration | JavaScript | No | Yes | No | Yes |
Jasmine | Unit | JavaScript | No | Yes | No | Yes |
In short, Jest is a highly popular testing framework for React that provides out-of-the-box support for snapshot testing, code coverage reporting, and DOM testing. Mocha and Jasmine are also popular testing frameworks for JavaScript, but they lack some of the features and support that Jest provides for React. All three frameworks have active communities and are suitable for testing React applications.
Let's dive into the features that make Jest a great choice for unit testing with React.
Integrated simulation
Jest makes it easy to isolate and test components by providing built-in simulation capabilities. You can use Jest's jest.mock function to create mock implementations of dependencies that your components depend on, making it possible to test your components without worrying about the behavior of your dependencies.
For example, let's say you have a component called MyComponent that depends on an external API function called getData . To simulate this API call in Jest, you can create a file called __mocks__/myApi.js with the following code:
export const getData = jest.fn( => Promise.resolve('mocked data'));
Then, in your test file, you can use jest.mock to replace the real myApi module with your mock implementation:
import { render, screen } from '@testing-library/react'; import { getData } from 'myApi'; import MyComponent from './MyComponent'; jest.mock('myApi'); test('renders data from API', async => { getData.mockResolvedValue('mocked data'); render(<MyComponent />); const data = await screen.findByText('mocked data'); expect(data).toBeInTheDocument; });
Snapshot Test
Snapshot testing with Jest allows you to capture the output of a component and compare it to a saved version of the same output. This helps detect any unintentional changes made to the component's output. To create a snapshot test for a component in Jest, you can add code to your test file that renders the component using dynamic prop data and saves its output as a snapshot.
To create a snapshot test for the MyComponent component in Jest, you can add the following code to your test file that will capture how it is rendered with dynamic data from its holder called data.
import renderer from 'react-test-renderer'; import MyComponent from './MyComponent'; test('renders correctly', => { const tree = renderer.create(<MyComponent data="test data" />).toJSON ; expect(tree).toMatchSnapshot; });
This will create a snapshot of the component's output when it is rendered with the data=”test data” property. If you make any changes to the component's output, Jest will notify you that the snapshot no longer matches, allowing you to investigate the changes and decide whether to update the snapshot or fix the code.
Fast and parallelized tests
Jest is designed to optimize speed by allowing tests to run in parallel, so that large projects with numerous tests don't suffer from slow test times and impede development progress.
Using Jest, you can run all your React application tests in parallel by running the following command in your terminal.
npm test -- --maxWorkers=4
This will run your tests with up to 4 workers, allowing Jest to run multiple tests at the same time and speeding up the overall testing process.
Integrated Code Coverage Report
Jest gives you the ability to quickly and easily assess how much of your codebase is covered by tests with its built-in code coverage report. These reports show precisely which parts of your code are being tested, so you can be sure that all vital areas have been covered. By reviewing these reports, you can determine where additional testing may be needed to ensure a robust and complete test suite.
npm test -- --coverage
This will run your tests and generate a code coverage report in the coverage directory. You can open the index.html file in your web browser to view the code coverage report.
Conclusion
Test-driven development (tdd) with Jest in React is a powerful tool to help React development companies and individual developers create reliable and bug-free applications. With its easy setup, intuitive interfaces, and comprehensive React library coverage, it's no wonder so many developers are choosing to use Jest for their unit testing.
Not only does it provide an efficient way to ensure code works as expected, but it also helps you find any issues quickly and accurately. The combination of Jest and React allows developers to produce robust applications that can be safely deployed in production environments. With all these benefits, there's no reason not to consider unit testing with Jest in React in your next project!
If you liked this article about React, check out these topics;
- React best practices
- React UI component libraries
- Top 6 React IDEs and Editors
- React vs Backbone JS
- Why is React so popular?
- What you need to know about react
- React WebSockets: Tutorial
Frequently Asked Questions (FAQ)
How do I run unit tests in Reactjs?
You can write your tests in a separate file and run them using the npm test command, which will automatically find and run your tests.
Which library is used for unit testing in React?
Jest is a popular library used for unit testing in React.
Why is the game so popular?
Jest is popular because it is easy to configure and use, has a simple and intuitive syntax, and provides a variety of features and tools for testing React applications.
Is Jest good for React unit testing?
Yes, Jest is a good choice for unit testing in React. It is designed specifically for testing JavaScript applications and provides a variety of features and tools for testing React components, including support for snapshot testing, simulation, and code coverage analysis. It is also widely used and well supported by the React community.
Source: BairesDev