Testing ReactJS applications using Jest and Enzyme

We are prone to error and this is what makes testing an integral part of software development. If done correctly, testing should give us confidence when developing our applications and also help us save time.

I was never a fan of test suites, I thought that if I could test my applications myself then why even bother automating the process. That was until my last year at the university. I had this school project which grew so huge and each time I presented it to my professor, there were always new bugs I have not noticed before. Sometimes solving these bugs led to some other new bugs. Automating these tests takes some time but they allow us to confidently test our applications in a matter of seconds.

ReactJS is a JavaScript library developed by Facebook for building user interfaces. A reactJS app is basically composed of actions, components, reducers, and selectors. We will see together how to test each of them.


Setting up Jest

Jest is a Javascript testing framework developed by Facebook. Documentation can be found at jestjs.io. The first step is installing Jest using npm or yarn, my favourite being yarn.

yarn add --dev jest

The next step is to adding a script that runs Jest in the package.json file.

"scripts": {
"test": "jest"
}

We can now move on to writing our tests. I am going to use the example of a diary application. I have never kept one so I am going to guess an entry consists of a date, a title, and a body. Let’s also add an id to make each entry unique.


Testing action generators

An action generator is like a “method” that returns an action which reducers can hear. For example, the addEntry action generator below lets the reducer know that we want to add a new entry with certain values to our diary.

It is a good practice to put all tests in a tests directory. Let’s add an entries.test.js file in the tests/actions directory

As you can see above, the first thing we do is import the action generators we want to test and then jump right into the text case. Each test has a brief description of what it is supposed to check. The action generator being tested is then called with the appropriate parameters and the action returned is stored in a variable. The last step is making an assertion. We except the returned action toBe, toEqual something. A list of all these functions can be found in the Jest documentation. Running the yarn test command will run all these tests and will either pass or fail.

Passing test suite
Failing test suite

A failed test suite lets us know exactly where the error is and what causes it. This facilitates debugging quite a lot.


Testing selectors

A selector can be thought of as a “GET method” which returns some data. Say we have some filters which filter the diary by text (title), sort it by date in ascending and descending order. We can have a selector that returns an array of diary entries according to these filters. Testing selectors is also done by making some simple assertions on what they are supposed to return.


Testing Reducers

Reducers are the parts of a ReactJS application that “listen” for actions. They expect some parameters and usually return an object or a value. Of course this can be changed if we are doing some extra operations but they are basically pure functions.

Testing reducers is not different from what we have done so far. We just need to import the reducer in question, call it with some parameters and make some assertions on what is supposed to be returned. There is however an additional test usually done to see if the application state is initialised correctly.


Testing Components

Testing components is a little different from what we have seen above. Here we want to see if the component is rendered correctly and how it handles user interaction. The former will normally require us to write the complete jsx the component renders which is impractical. This is where Enzyme comes in handy.


Setting up Enzyme

Enzyme is a JavaScript Testing utility for React developed by Airbnb. Documentation can be found at airbnb.io/enzyme. Enzyme will allows us to render our components and use Snapshots testing. The installation varies with the version of React used. For React v16, it is also required to install the modules enzyme-adapter-react and raf (a browser feature called request animation frame). An enzyme to json module can also be added to make snapshots more understandable. You can install all of them as shown below specifying the version you want.

yarn add enzyme@3.0.0 enzyme-adapter-react-16@1.0.0 raf@3.3.2 enzyme-to-json@1.5.1

We then need to setup the enzyme adapter. We can just do it once by creating a setup file in the tests directory.

The next thing to do is adding a Jest setup file to pick up the Enzyme setup automatically before running the test suites. We do that by adding jest.config.json file at the root of the application.

{
"setupFiles" : [
"raf/polyfill",
"<rootDir>/src/tests/setupTests.js"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}

The last thing to do is to update the test script in the package.json file.

"scripts": {
"test": "jest --config=jest.config.json"
}

Let’s check if the installation was done correctly by say testing a header using snapshots.

A snapshot will be generated the first time this runs and subsequently, the rendered Header output will be compared to that snapshot.


Mocking Libraries

Mocking libraries is one of the techniques used in testing components. So many libraries are generally used when developing a React application. In the actions section above, we used the Uuid library to generate a random string value for the id’s and we were able to test the action generator by expecting any string value. This does not always work out though.

If we want to add a new entry in a diary application, we will probably need a calendar/datepicker to select the date and we may want today’s date to be selected by default. We cannot just expect a random date while testing the AddEntry component and the test will fail if the rendered date does not match the one in the snapshot.

Mocking allows us to change the behaviour of a library in our tests. The most commonly used library when interacting with date and time is Moment and we are going to mock this library. The mocks should be located in a directory in tests called __mocks__.

What the code above does is each time moment() is called to return the current moment in time, it will instead return midnight on the 1st of January 1970. Thanks to this the snapshot will always match as long as there is no bug in the component.

Testing user interaction

A component also include click events handler, submit events handlers, and so on. We are going to see how simulate these events using the find and simulate functions.

The simulate function takes in the event and an optional event object as parameters.

Spy functions

Spy functions are also known as mocked functions. So far we know how to render our components and simulate events. But we do not know if the event handlers are called with the correct values. Below is an example of how to check just that.

Creating spy functions is simply done by calling the function jest.fn(). These functions are passed to the component and we can then make as many assertions as we want on how they were called. All of these functions can be found in the Jest documentation.

Lastly, I want to talk about the beforeEach function. This is one of the functions offered by Jest to make our codes more concise. beforeEach for instance runs before each test cases and helps us avoid repetition.

This is all for this post, I hope it gave you a little insight on Jest and Enzyme and I also hope you get to enjoy testing your React applications using these libraries.


If you liked it, don’t forget to show 💛 through 👏 👏 👏 and follow me on Medium or LinkedIn. Your remarks and suggestions would be greatly appreciated.