1
votes

I am having trouble testing a function with concurrent API calls. Here's the code I want to test that relies on redux-thunk :

const loadResources = () => {
  return (dispatch) => {
    dispatch(setLoaderState(true))
    // events
    API.get('/internal/timeo/api/v0/actions')
      .then(response => initialFetchEventsSuccess(dispatch, response))
      .catch(error => onRequestErrorCallback(dispatch, error));
    // clients
    API.get('/internal/obeya/api/v0/clients')
      .then(response => initialFetchClientsSuccess(dispatch, response))
      .catch(error => onRequestErrorCallback(dispatch, error));
    // resources
    API.get('/internal/obeya/api/v0/resources')
        .then(response => getRessourcesSuccess(dispatch, response))
        .catch(error => onRequestErrorCallback(dispatch, error));
  }
}

// on successfull fetch we dispatch data to the store
const initialFetchEventsSuccess = (dispatch, data) => {
  dispatch(setLoaderState(false))
  dispatch(setErrorState(false))
  dispatch({
    type: LOAD_EVENTS,
    payload: data.data
  });
}

// on successfull fetch we dispatch data to the store
const initialFetchClientsSuccess = (dispatch, data) => {
  dispatch(setLoaderState(false))
  dispatch(setErrorState(false))
  dispatch({
    type: LOAD_CLIENTS,
    payload: data.data
  })
}

// on successfull fetch we dispatch data to the store
const getRessourcesSuccess = (dispatch, data) => {
  dispatch({
    type: SET_RESOURCES,
    payload: data.data
  })
}

It sends concurrent request to the API and then dispatches actions to the redux store upon success. Those requests are independent so I dont really care which one gets executed first.

However when I try to test this code with moxios and redux-mock-store I only get actions dispatched from the first request in my mocked store :

it('loadsResources', async (done)=> {
    moxios.stubRequest('/internal/timeo/api/v0/actions', {
      status: 200,
      response: getActionsMock
    });
    moxios.stubRequest('/internal/timeo/api/v0/clients', {
      status: 200,
      response: getClientsMock
    });
    moxios.stubRequest('/internal/timeo/api/v0/resources', {
      status: 200,
      response: getResourcesMock
    });

  const expectedActions = [
     { type: LOAD_EVENTS, payload: getActionsMock},
     { type: LOAD_CLIENTS, payload: getClientsMock},
     { type: SET_RESOURCES, payload: getResourcesMock},
  ]
  const store = makeMockStore({});


  await store.dispatch(loadResources);

  setTimeout(() => {
    const actions = store.getActions();
    console.log(actions)
    done();
  }, 1000);
});

Here in actions I only get the LOAD_EVENTS action in the end, whatever timeout I set up. What am I doing wrong ?

1

1 Answers

1
votes

Late to answer maybe but I came across this in moxios repo while looking for similar answer.

https://github.com/axios/moxios#mocking-a-axioscreate-instance

So, you are in the right direction. Just need to assert axios instances and get results that way.

 let axiosInstance;

 beforeEach(() => {
    axiosInstance = axios.create();
    moxios.install(axiosInstance);
 });

 afterEach(() => {
    moxios.uninstall(axiosInstance);
 });

 test('Should get results', (done) => {
    moxios.stubRequest(`url`, {status: 200, response: response /* or response */});
    axiosInstance.get(`url`)
      .then(res => res.status === 200)
      .finally(done)
 })