Testing async actions in redux with isomorphic fetch and fetch-mock

kellyrmilligan
3 min readApr 19, 2017

I was recently digging in on a new react project with a pretty standard setup:

  • redux
  • react-redux
  • redux-thunk
  • react-router
  • isomorphic-fetch
  • jest

I was starting to focus on code coverage, posting results to codecov.io to keep track of the trends, etc. After a few screens had been developed, I wanted to go back through and tighten up some of the tests, especially async actions. I had very purposefully avoided testing the thunk action creator to keep things simple, but wanted to establish a pattern for the rest of the team to test these things with adequate coverage as it will only grow over time.

I started by re-reviewing the guide for testing on redux:

example from the docs regarding async action creators:

import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as actions from '../../actions/TodoActions'
import * as types from '../../constants/ActionTypes'
import nock from 'nock'
import expect from 'expect' // You can use any testing library

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

describe('async actions', () => {
afterEach(() => {
nock.cleanAll()
})

it('creates FETCH_TODOS_SUCCESS when fetching todos has been done', () => {
nock('http://example.com/')
.get('/todos')
.reply(200, { body: { todos: ['do something'] }})

const expectedActions = [
{ type: types.FETCH_TODOS_REQUEST },
{ type: types.FETCH_TODOS_SUCCESS, body: { todos: ['do something'] } }
]
const store = mockStore({ todos: [] })

return store.dispatch(actions.fetchTodos())
.then(() => { // return of async actions
expect(store.getActions()).toEqual(expectedActions)
})
})
})

in the code above this, isomorphic-fetch is used, so I thought, “this is going to be dead simple”. I had used nock before in other node projects, and it is great! I started writing the tests in jest using this example as my template. With nock , it never intercepted the request made by fetch. I started digging around and found this issue on github:

and this:

fetch-mock is mentioned in both issues, and I decided to give it a shot.

I was able to adjust the template pretty easily using fetchMock, and wanted to share a generic example:

import * as actions from './index'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import fetchMock from 'fetch-mock'

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

const mockResult = { ...some data }
describe('action creators', () => {

it('should create SEARCH_SUCCESS when searching', () => {
fetchMock.getOnce('/search?q=searchterm', mockResult)

const expectedActions = [
{ type: actions.SEARCH_LOADING },
{ type: actions.SEARCH_SUCCESS, payload: mockResult }
]
const store = mockStore({ search: {
result: {}
}})

return store.dispatch(actions.search('searchterm'))
.then((data) => { // return of async actions
expect(store.getActions()).toEqual(expectedActions)
})

})

})

I’m using the getOnce shortcut method in this example, but see the documentation for all the other forms of mocking requests. I hope this helps folks increase their code coverage in their redux based projects!

--

--