Moxios or Nock To Mock
Tags: redux, testing
Published: 2017-12-11 17:06:11

---
title: Moxios or Nock To Mock
published: true
description: Testing async action creators using moxios
cover_image: https://img.devrant.com/devrant/rant/r_1010209_zoD5N.jpg
tags: redux, testing
---
I recently came across an interesting hurdle when testing async action creators. I was testing whether a delete action creator is called when the thunk runs. The code below shows a thunk and an action creator respectively. 
```javascript
/**
 * Delete user contribution thunk
 *
 * @param {string} contribution for the contribution to be deleted
 * @return {(dispatch) => Promise<TResult2|TResult1}
 */
export const deleteUserContribution = (contribution) => {
  return ((dispatch) => {
    return http.delete(`${config.API_BASE_URL}/contributions/${contribution.id}`)
      .then((response) => {
        dispatch(deleteUserContributionSuccess(contribution.id));
      });
  });
};

/**
 * Delete user contribution action creator
 *
 * @param {string} contributionId for the contribution to be deleted
 * @return {IDeleteUserContributionSuccess}
 */
export const deleteUserContributionSuccess = (contributionId): IDeleteUserContributionSuccess => {
  return { type: DELETE_USER_CONTRIBUTION_SUCCESS, contributionId };
};
```
I used nock at first to mock requests. 

```javascript
// third party libraries
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { expect } from 'chai';
import * as moxios from 'moxios';

// fixtures
import { sampleContribution } from '../fixtures/contribution';

// actions
import { deleteUserContribution } from './ContributionActions';

// types
import { DELETE_USER_CONTRIBUTION_SUCCESS }  from '../types';

const middleware = [thunk];
const mockStore = configureMockStore(middleware);
let store;
let url;

describe('Async Contribution Actions', () => {
 it('creates DELETE_USER_CONTRIBUTION_SUCCESS when deleting a contribution', () {
     nock(`${config.API_BASE_URL}`)
      .delete(`/contributions/${contribution.id}`)
      .reply(204,'')

     const expectedActions = [
     { type: DELETE_USER_CONTRIBUTION_SUCCESS, contributionId: sampleContribution.id },
];

    return store.dispatch(deleteUserContribution(sampleContribution)).then(() => {
      const actualActions = store.getActions();
      expect(actualActions).to.eql(expectedActions);
    });
  });
})
```
I ran the test and it passed. I then proceeded to make a PR for the delete feature and requested a review from my team. A team member who was also writing async action tests slacked me and pointed out that _package.json_ already has Moxios and that I could leverage on that rather than install a new mock library. I decided to try it out. I followed the Moxios documentation and implemented it. However I got error below.

```terminal
 1) Async Contribution Actions
       creates DELETE_USER_CONTRIBUTION_SUCCESS when deleting a contribution:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
```
I added the _done()_ just after expect but the above error showed up.
I decided to slack the team member who encouraged me to use Moxios and before I even asked anything he had already sent me a message. The message detailed that he had pulled my branch and broke my test by changing the expect to be something like so

```javascript
return store.dispatch(deleteUserContribution(sampleContribution)).then(() => {
      const actualActions = store.getActions();
      expect(actualActions).to.eql(1);
    });
```

and he told me the test was still passing. He also added that he had the same issue where nock seemed to not perform its work correctly therefore moved to Moxios. I was skeptical at first but I decided to investigate the matter. Lo and behold I found that nock was just resolving the promise and not returning the data I had told it to return. The only bit that still has me baffled was why the expect was still working. I implemented the test using Moxios and it worked as follows. The imports and middleware remained the same.

```javascript
describe('Async Contribution Actions', () => {
  beforeEach(() => {
    moxios.install();
    store = mockStore({});
    url = `${config.API_BASE_URL}`;
  });
  afterEach(() => {
    moxios.uninstall();
  });

  it('creates DELETE_USER_CONTRIBUTION_SUCCESS when deleting a contribution', (done) => {
    moxios.stubRequest(`${url}/${sampleContribution.id}`, {
      status: 204,
      response: { data: '' },
    });

    const expectedActions = [
      { type: DELETE_USER_CONTRIBUTION_SUCCESS, contributionId: sampleContribution.id },
    ];

    store.dispatch(deleteUserContribution(sampleContribution)).then(() => {
      const actualActions = store.getActions();
      expect(actualActions).to.eql(expectedActions);
      done();
    });
  });
});
```

I tried to break the test by adding a false actual value and it failed meaning  Moxios did a better job. I know the redux documentation uses fetch-mock but I suspect it was using nock before. 

The question I probably have now for you is what do you use to test async action creators ?