There are many libraries available for React.JS testing. You would have probably heard about Jest
, Enzyme
, React Test Utils
, React Testing Library
, Dom Testing Library
and many more. There are other libraries that help you assert in the unit testing library like chai
, expect
, sinon
.
In this tutorial, we are going to look into testing react.js applications using a library called React Testing Library
.
React Testing Library is a lightweight testing library aimed at providing good test practices. What are these best practices? One of the rules for testing is that the unit tests should not be brittle. The unit tests should test the functionality of the components/function and not its implementation. react-testing-library
is meant to be the replacement for enzyme
, another popular testing library from Airbnb.
react-testing-library
is a wrapper on top of dom-testing-library
. The primary goal of dom-testing-library
is to test just as your user uses the application. Your users do not care how you are implementing the functionality, they care if it works as intended. By writing tests that closely resemble the way users use your system, you cut down on writing un-necessary tests and catch bugs faster.
react-testing-library
also does not provide methods to test on the instance of the reactjs component. You only get the methods to test the dom, which resembles the way the user uses your application. Because you do not have methods to get an instance of the component, you do not write tests that test the implementation of the component.
Install the library in your reactjs project using the command
npm install react-testing-library --save-dev
So you package.json
should be updated with devDependencies with following "react-testing-library". At the time of writing this tutorial, the latest version of react-testing-library
was 6.1.2, it might be different when you install the library.
"devDependencies": {
...
"react-testing-library": "^6.1.2"
...
},
We are going to take an example of a simple React component that has a button that increments the number and displays it on screen. (If you have read other Techdomain tutorials, this example is our choice, but it is really simple to understand)
This is the example of App.js component
import React, { Component } from 'react';
export default class App extends Component {
state = {
number: 0
}
incrementNumber = () => {
const { number } = this.state;
this.setState({
number: number + 1
})
}
render() {
const { number } = this.state;
return (
<div>
<div data-testid="increment-number">
{number}
</div>
<button data-testid="increment-button" onClick={this.incrementNumber}>
Increment Number
</button>
</div>
)
}
}
We are going to use two APIs from react-testing-library
import { render, fireEvent } from 'react-testing-library';
We will test the functionality of the component - when the user clicks on the button, the updated number should be displayed on the screen.
This is the test for the above functionality.
import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import App from './App';
describe('App Tests', () => {
it('should increment number', async () => {
const wrapper = render(<App />);
let index = await wrapper.findByTestId('increment-number');
expect(index.textContent).toEqual("0");
fireEvent.click(wrapper.getByTestId('increment-button'))
index = await wrapper.findByTestId('increment-number');
expect(index.textContent).toEqual("1");
})
})
We are using an async function here because of some of the methods of react-testing-library
return promise (like findByTestId
).
We get the instance of app using render
function
const wrapper = render(<App />);
Then we search for the DOM using the data-testid
attribute for the number to check if it shows the initial state as 0.
let index = await wrapper.findByTestId('increment-number');
expect(index.textContent).toEqual("0");
Using fireEvent
, we fire a click event from the increment button.
fireEvent.click(wrapper.getByTestId('increment-button'))
Then we test if the number on screen is incremented by 1
index = await wrapper.findByTestId('increment-number');
expect(index.textContent).toEqual("1");
It's very easy to get started with react-testing-library and write maintainable tests. To sum it up, using react-testing-library, you are going to save time writing an un-necessary test and write maintainable tests that do not break when someone changes the functionality of the component.