Unit testing with Jest: Redux + async actions + fetch

Using Jest v20

Ferran Negre
4 min readMay 19, 2016

LAST UPDATE: June 24, 2017. Original writing: May 19, 2016.

I have been using Jest since its beginnings. I won’t lie, the path has been painful: Things like updating from version 0.x.0 to version 0.y.0 (specially to version 0.4.0) was particularly terrible for my tests. Furthermore, I struggled myself more than once with the way Jest works and I even bothered the community with questions like 1, 2, and 3.

But stay with me, Jest has also good things that I am going to show you in a moment. I hope somebody will find this particularly useful because, in my humble opinion, the biggest drawback of Jest is its lack of real examples.

Recently (May 19, 2016), I’ve been writing an app with the React/Redux combo. It uses an external API and I decided to use a fetch polyfill in order to make my network requests. Following the Redux-way, I’ve used Async Action Creators in combination with redux-thunk. Here is how my action looks like:

(Notice that nowadays you can use async/await too).

Ok, now, let’s test it step by step based on the WritingTests from the Redux docs.

A big change here since I first wrote this article in 2016 is that Jest now does not mock your dependencies automatically like it used to. You can read more about it on its blog: Jest 15 — Disabled automocking

Therefore, we do not need to manually unmock modules we want to test.

On the contrary, we are going to use redux-mock-store which is a small package that will help us mocking a redux store as it’s name suggests. Basically, it emulates the redux store (same API) but just for test purposes. You can check the code which is very simple.

Let’s get started! We import everything we need:

import { fetchData } from '../api';
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);

And I am also going to write a helper method to mock the fetch response (we don’t need nock as suggested in the Redux Writing Test example):

const mockResponse = (status, statusText, response) => {
return new window.Response(response, {
status: status,
statusText: statusText,
headers: {
'Content-type': 'application/json'
}
});
};

After that, let’s actually write our first it (previously we needed to use pit for async test: Not anymore)

Do you see what I am doing? I don’t care what the real fetch does, I will reinvent it with jest.fn().mockImplementation and force it to return the response I want to test with (in this case a successful one). And with that, I assert that two and only two actions have been called and that they are FETCH_DATA_REQUEST and FETCH_DATA_SUCCESS.

Very similar with the error test case:

Well done! Let’s go one step further, remember this?

if(getState().id === id)) {
return; // No need to fetch
}

Well, that might be the most basic caching system in the world. Let’s see how can we easily test that too:

See, I am mocking a new store that already has the id 1234 ‘fetched’, so if we dispatch our action, window.fetch should not be called because it is the same id we already “fetched”. Instead, it should be called if it is a different one. As you can see, I don’t even care what fetch returns here so I just make it to return a Promise.

With that, we got our async action fully covered. But wait! It’s not over, there is a bonus and this is very important. Do you remember the import at the beginning of our example action code?

import ‘whatwg-fetch’

If you or your team forget to use the polyfill version of fetch, Chrome or FF will still work and you won’t notice it! But poor the user who tries to use your website on older versions or other browsers if you know what I mean. For that reason, we will write a unit test to avoid such case too. Look at the polyfill code, it has:

self.fetch.polyfill = true

Awesome, we can write a test like:

it('makes sure window.fetch is the one from the polyfill', () => {
expect(window.fetch.polyfill).toBe(true);
});

Splendid Jest!

And that’s it my friends, this is actually everything I wanted to show you. If you find a similar example with Jest, please share it because it does get really hard to find them. Thanks to the Redux docs for the great explanation of how we can test those async actions and for the mocha example (2017 note: They changed the example to use Jest!).

By the way, this is my first article in Medium, I hope you enjoyed, thanks for reading and hopefully, write you soon!

--

--

Ferran Negre

Software Engineer specialized in React Native • Created @fitheroapp and @audioprofiles. More at ferran.dev