Write test axios-mock-adapter with axios.create()

user990993 picture user990993 · Jul 10, 2018 · Viewed 11.9k times · Source

I want to test my http service but get error. So, my test file

api.js

import axios from 'axios';

export const api = axios.create();

fetchUsers.js

import api from './api';
export const fetchUsers = (params) api.get('/api/users', { params })
  .then(({data}) => data)

fetchUsers.spec.js

import MockAdapter from 'axios-mock-adapter'
import api from './api';
const mock = new MockAdapter(api);

describe('fetchUsers', () => {
  it('should send request', (done) => {
    const data = { data: ['user'] };
    mock.onGet('/api/users').reply(200, data);

    fetchUsers().then((response) => {
      expect(response).toEqual(data.data);
      done();
    });
  });
});

But I get error here

Error: connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1158:14)

If I replace in api.js axios.create() with axios its' working. But how to test with created axios instance? I'll need to ass there parameters when create it.

Anyone can help with that?

Answer

kyw picture kyw · Jul 19, 2018

Hi I had the same issue and had to answer myself here https://stackoverflow.com/a/51414152/73323

Here is the gist:

First off, you don't need the axios-mock-adapter library.

Create a mock for axios in src/__mocks__:

// src/__mocks__/axios.ts

const mockAxios = jest.genMockFromModule('axios')

// this is the key to fix the axios.create() undefined error!
mockAxios.create = jest.fn(() => mockAxios)

export default mockAxios

Then in your test file, the gist would look like:

import mockAxios from 'axios'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

// for some reason i need this to fix reducer keys undefined errors..
jest.mock('../../store/rootStore.ts')

// you need the 'async'!
test('Retrieve transaction data based on a date range', async () => {
  const middlewares = [thunk]
  const mockStore = configureMockStore(middlewares)
  const store = mockStore()

  const mockData = {
    'data': 123
  }

  /** 
   *  SETUP
   *  This is where you override the 'post' method of your mocked axios and return
   *  mocked data in an appropriate data structure-- {data: YOUR_DATA} -- which
   *  mirrors the actual API call, in this case, the 'reportGet'
   */
  mockAxios.post.mockImplementationOnce(() =>
    Promise.resolve({ data: mockData }),
  )

  const expectedActions = [
    { type: REQUEST_TRANSACTION_DATA },
    { type: RECEIVE_TRANSACTION_DATA, data: mockData },
  ]

  // work
  await store.dispatch(reportGet())

  // assertions / expects
  expect(store.getActions()).toEqual(expectedActions)
  expect(mockAxios.post).toHaveBeenCalledTimes(1)
})