Flawless React/Redux Testing with the Jest Framework - Part 1
Testing a React/Redux app can be a problem. Recently, with new tools being created every day, choosing the right tool has become harder than ever. In this article, I will show you how to use Jest to get your tests done.
- built-in support for DOM with jsdom inside,
- integrated manual mocking library,
- support for testing asynchronous code,
- watch mode! – runs tests only on files that changed,
- automatic coverage reports' creation,
- snapshot testing – creates snapshots of generated content and compares them in order to simplify UI testing.
To get started with Jest, you can download the create-react-app package, which is a convenient way to bootstrap new personal projects.
$ npm install -g create react-app
$ create-react-app netguru-react-redux-1
$ cd netguru-react-redux-1 && npm start
Now you can launch your tests in the watch mode with:$ npm test
which runs under the hood:$ jest --watch
In every React/Redux project, you need to create and test at least four things: reducer, actions, component, container. In this tutorial, we will take a look at the first two.
Let’s assume we have an app that loads the quotes from a remote server. Our reducer can look as follows:
Testing the reducer is pretty straightforward. No magic here.
Hint: we are using toEqual instead of toBe because we need to compare objects by value. The toEqual performs a deep equal, so it’s needed for objects or arrays.
It is a good practice to check whether the reducer outputs the desired initial state and to check if it returns the current state once an unknown action is dispatched. In other words, you’d rather want to check that it doesn’t lose the state while we perform an action on some other part of the state tree. Believe me, this simple check can sometimes save hours of debugging.
Our action is also very basic. As soon as we execute it, it dispatches the FETCH_QUOTES_REQUEST, so we can use it to show, e.g. a loading indicator.
Next, it calls the API and, depending on the response, it dispatches FETCH_QUOTES_SUCCESS with the data or FETCH_QUOTES_FAILURE.
In order to dispatch redux actions asynchronously, we need to use redux-thunk apart from redux. One important thing here: we need to return the promise from our action so that Jest knows how to handle it and waits for it to resolve.
Things are getting interesting here. We need to test two scenarios: (1) the server responds with a valid response, and (2) the server responds with an error. We use the fetch-mock package to simulate server responses, which has a really simple API. We also need redux-mock-store, which provides a useful method to check dispatched actions. Similarly to what we did in the action, we also need to return the promise here to let Jest know how it should handle it.
Bear in mind that we need to call the fetchMock.restore(); method to reset the fetch mock and use a different response for our request in the next test case. It’s good to put that kind of resets in the afterEach function which is run after each test case – this way, our tests will stay nice and clean.
Stay tuned for our future posts! We will test the React part of the app and use more Jest‘s features to create a complete testing suite.