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, launched in May 2013, is one of the most popular JavaScript libraries for creating user interfaces in web applications. Jest is the most widely-used test framework for unit testing React components.
This article will explore Jest to write unit tests for React components. We’ll look at what makes up a unit test, how to write tests using Jest’s APIs and assertions 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 setup process, among other features. All these features allow you to quickly write meaningful tests without getting bogged down in configuration details or dealing with complex setup processes for each tool separately.
To effectively utilize Jest for writing unit tests in React applications, you must first understand how different types of assertions work, what mocking means, and the best practices around setting up your environment. This article will provide an overview of all these topics so readers can gain enough knowledge to write meaningful yet maintainable unit tests in no time!
Why is Unit Testing Important?
Unit testing is essential for several reasons, some of which are mentioned as follows:
Reduced Development Time
Unit testing can reduce the time spent on debugging by preventing errors from appearing later in the development cycle. By writing unit tests before coding, React developers can quickly identify any problems with their code before going too deep into implementation.
This allows them to make tweaks or fixes as soon as possible without starting over completely from scratch if something goes wrong. Additionally, once a suite of unit tests has been written for an application, it can be run again after any major changes have been made to ensure that everything works as expected.
Improved Code Quality
By running automated unit tests regularly during development, developers can catch mistakes and inconsistencies early on before they become much bigger problems later on down the road. Writing comprehensive test cases also encourages better coding practices since it requires programmers to think ahead about what inputs may lead to unexpected results or bugs further along in the development process.
As a result, a unit test often lead to improved overall code quality and fewer bugs compared with projects that do not employ this testing method or only partially implement it during their workflow.
Better Documentation
Programmers that write unit tests help to create clear documentation for each part of an application because every step a programmer takes must be thoroughly documented so that other programmers or engineers working with that same piece of software understand exactly what was done and why it was done this way rather than another way.
Additionally, good documentation helps future maintenance personnel maintain existing applications more easily since 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.
Higher Reliability & Maintainability
Unit tests help ensure reliability because they check for bugs at each level throughout an entire application’s lifecycle. When these checks fail due to new errors being introduced into an application, developers can immediately address them instead of waiting until later to repair damage caused by unnoticed bug(s).
This increased level of monitoring also means less time wasted trying to track down sources of various issues since most have already been caught beforehand through rigorous react unit testing procedures.
In addition, maintainability increases significantly when multiple sets of test cases cover different aspects of functionality within the chosen area (e.g., user interface logic), meaning future updates/changes need only pass established criteria set up previously; the order remains valid after modifications occur.
What is Jest?
Jest is a JavaScript testing framework created by Facebook. It performs unit and integration tests 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 the implementation of Unit Tests in React!
How Can We Implement Unit Tests in React?
Let’s look at how we can implement unit testing 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.
- Jest: A JavaScript testing framework that works well with React.
- React Testing Library: It provides utilities for testing React components.
Getting Started
Installing and Creating a New React App
Run the following command in your terminal to install Create React App. It is a tool that initializes a react app with no build configuration.
$ npm install create-react-app
Once Create React App is installed, you should run the following command.
$ npx create-react-app my-app
Now navigate to the my-app directory.
$ cd my-app
Execute the following command to start the React application 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: http://localhost:3000 On Your Network: http://address:3000 Note that the development build is not optimized. To create a production build, use npm run build. webpack compiled successfully
When you go to the URL http://localhost:3000/, you will see a default page for the React Application.
We need to install Jest and React Testing Library as a dev dependency.
Installing Jest Using Terminal
Run the following command in your terminal to install Jest.
$ npm install --save-dev jest
Installing React Testing Library Using Terminal
Run the following command in your terminal to install 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 run the tests automatically whenever called.
This is how the package.json looks right 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 pick up files that end with .test.js or .spec.js in the project directory.
Writing a Unit Test Case
Another important thing to know is how to write a unit test case.
Type of Query | 0 Matches | 1 Match | > 1 Matches | Retry (Async/Await) |
Single Element | ||||
getBy... |
Throw error | Return element | Throw error | No |
queryBy... |
Return null | Return element | Throw error | No |
findBy... |
Throw error | Return element | Throw error | Yes |
Multiple Elements | ||||
getAllBy... |
Throw error | Return array | Return array | No |
queryAllBy... |
Return [] | Return array | Return array | No |
findAllBy... |
Throw error | Return array | Return array | Yes |
Source: Testing Library Documentation
To summarise:
- You are to use getBy, findBy, or queryBy when selecting a single DOM element.
- You are to 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, then a null value is returned else if there is more than one match, an error is returned by queryBy
- getBy and queryBy do not work well with asynchronous code, whereas findBy does.
- If there is any match, then an array of matches is returned else, an error is given by the getAllBy query.
- If there is any match, then an array of matches is returned else, an error is given by the findAllBy query.
- If there is any match, then an array of matches is returned else, an empty array is returned by the getAllBy query.
Now that you’re familiar with query methods, let’s start to write a unit test case for the React component.
Let’s create a component first. Create a new file with the name of the component. 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 default App;
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 render feature from @testing-library/react for use in a test environment.
We then bring our MyComponent into scope and apply the render function to it. Finally, with getByText, we can retrieve “Hello World” text and check its presence using expect().
To run this test, type the following command in your terminal window:
$ npm test
The output should be as follows:
If you change the contents of the div and run the test command. 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 both props and state. It is essential to test that these values are being set and updated correctly. Let’s update our MyComponent example to test a prop:
// 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 that the component renders the correct name prop. We pass the prop to the component when we render it using the render method. We then use the getByText method to retrieve the “Hello Baires” text and check that it is in the document using the expect method.
The testing state is similar to testing props. 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 that the count state updates 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 that the count element initially has a value of 0, simulate a click event using the fireEvent method, and check that the count element has a value of 1.
Why Is Jest a Great Choice for Unit Testing In React?
Here’s a comparison of a few popular testing frameworks.
Framework | Testing Type | Language | DOM Testing | Code Coverage | Snapshot Testing | Active Community |
Jest | Unit | JavaScript | Yes | Yes | Yes | Yes |
Mocha | Unit and Integration | JavaScript | No | Yes | No | Yes |
Jasmine | Unit | JavaScript | No | Yes | No | Yes |
In a nutshell, 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 dig deeper into what features make Jest a great choice for Unit Testing with React.
Built-in Mocking
Jest makes isolating and testing components easy by providing built-in mocking capabilities. You can use Jest’s jest.mock() function to create mock implementations of dependencies that your components rely on, making it possible to test your components without worrying about their dependencies’ behavior.
For example, let’s say you have a component called MyComponent that relies on an external API function called getData(). To mock 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 Testing
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 unintended changes made to the component’s output. To create a snapshot test for a component in Jest, you can add code in your test file that renders the component using dynamic data from props 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 which will capture how it renders with dynamic data from its prop 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’s rendered with the prop data=”test data”. 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 Testing
Jest has been designed to optimize speed, allowing tests to be run in parallel so that large projects with numerous tests do not suffer from slow testing times and impede development progress.
Using Jest, you can run all tests for your React app in parallel by executing the following command in your terminal.
npm test -- --maxWorkers=4
This will run your tests with up to 4 workers, allowing Jest to execute multiple tests at the same time and speeding up the overall testing process.
Built-in Code Coverage Reporting
Jest gives you the ability to quickly and easily assess how much of your codebase is covered by tests with its integrated code coverage reporting. These reports show precisely which parts of your code are being tested, so that you can make sure all vital areas have been addressed. 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 both React development companies and individual developers create reliable, bug-free applications. With its easy configuration, intuitive interfaces and comprehensive coverage of the React library, it’s no wonder why so many developers are choosing to use Jest for their unit testing.
Not only does it provide an efficient way to ensure that code performs as expected but also helps find any issues quickly and accurately. The combination of Jest and React allows developers to produce robust applications that can be confidently deployed into production environments. With all these benefits, there’s no reason not to consider unit testing with Jest in React for your next project!
If you enjoyed this article on React, check out these these topics;
- React Best Practices
- React UI Component Libraries
- The Best 6 React IDEs & Editors
- React vs Backbone JS
- Why React Is So Popular?
- What You Need to Know About React
- React WebSockets: Tutorial
Frequently Asked Questions (FAQs)
How Do I Run the 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 Jest So Popular?
Jest is popular because it is easy to set up and use, has a simple and intuitive syntax, and provides a range 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 range of features and tools for testing React components, including support for snapshot testing, mocking, and code coverage analysis. It is also widely used and well-supported by the React community.