1
votes

I'm creating a simple action to fetch some data from an API with Thunk. It looks like this:

import fetch from 'isomorphic-fetch';

function json(response) {
  return response.json();
}

/**
 * Fetches books from the server
 */
export function getBooks() {
  return function(dispatch) {
    fetch("http://localhost:1357/book", {mode: "cors"})
    .then(json)
    .then(function(data) {
      dispatch({
        type: "GET_BOOKS",
        devices: data
      });
    });
  }
};

It should call fetch once. I have verified that it does this, because it successfully pulls data when called in a web browser. However, when I write this test:

import fetch from 'isomorphic-fetch';
let spy = sinon.spy(fetch);
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import {getBooks} from '../../actions/getBooks';
import sinon from 'sinon';

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

describe('async actions', () => {

  it('calls the server', () => {
    const store = mockStore({books: []});
    store.dispatch(getBooks());
      expect(spy.callCount).toEqual(1);
      spy.restore();
  });
});

However, this test fails, and the spy's call count is 0. I suspect this is due to fetch being imported by the action before the test, which is why the spy is created at the top of the file. However, this does not work. What is the recommended way to test that fetch is being called?

1

1 Answers

1
votes

Reading from http://arnaudbenard.com/redux-mock-store/, part Asynchronous action.

I'm guessing it happens because you are not using a promise in your test.

it('calls the server', (done) => {
    const store = mockStore({books: []});
    store.dispatch(getBooks()).then(() => {
      expect(spy.callCount).toEqual(1);
      spy.restore();
      done();
    });
  });