Как издеваться над классом axios

Пишу тесты для своих асинхронных действий. Я выделил свои вызовы аксиом в отдельный класс. Если я хочу протестировать свое асинхронное действие redux, как мне написать макет для api.js, чтобы sampleAction.test.js прошел? Спасибо!

api.js:

import axios from 'axios';

let apiUrl = '/api/';
if (process.env.NODE_ENV === 'test') {
  apiUrl = 'http://localhost:8080/api/';
}

export default class Api {
  static async get(url) {
    const response = await axios.get(`${apiUrl}${url}`, {withCredentials: true});
    return response;
  }
}

sampleAction.js: импортируйте Api из './api';

export const fetchData = () => async (dispatch) => {
  try {
    const response = await Api.get('foo');
    dispatch({
      type: 'RECEIVE_DATA',
      data: response.data.data,
    });
  } catch (error) {
    handleError(error);
  }
};

sampleAction.test.js:

import store from './store';

test('testing RECEIVE_DATA async action', () => {
  const expectedActions = [
    { type: 'RECEIVE_DATA', data: 'payload' },
  ];
  return store.dispatch(actions.fetchData()).then(() => {
    expect(store.getActions()).toEqual(expectedActions);
  });
});

person Jimmy    schedule 15.04.2019    source источник
comment
Вы смотрели github.com/axios/moxios?   -  person Charlie Stanard    schedule 16.04.2019
comment
Спасибо @CharlieStanard, я взглянул на это. Я вижу, что он ссылается на насмешку над экземпляром axios.create (), однако я просто очень смущен, если это то, что я должен использовать для имитации, и как это сделать. То есть, если бы я назвал это издевательством, что бы случилось? Разве я не хочу, чтобы он имитировал переданный URL и возвращал определенное значение?   -  person Jimmy    schedule 16.04.2019
comment
Также см. github.com/ctimmerm/axios-mock-adapter.   -  person TrueWill    schedule 16.04.2019


Ответы (1)


Вы можете издеваться над Api.get вот так:

import { fetchData } from './sampleAction';
import Api from './api';

let getMock;
beforeEach(() => {
  getMock = jest.spyOn(Api, 'get');
  getMock.mockResolvedValue({ data: { data: 'mock data' } });
});
afterEach(() => {
  getMock.mockRestore();
});

test('testing RECEIVE_DATA async action', async () => {
  const dispatch = jest.fn();
  await fetchData()(dispatch);
  expect(getMock).toHaveBeenCalledWith('foo');  // Success!
  expect(dispatch).toHaveBeenCalledWith({
    type: 'RECEIVE_DATA',
    data: 'mock data'
  });  // Success!
});

... или вы можете издеваться над api.js вот так:

import { fetchData } from './sampleAction';
import Api from './api';

jest.mock('./api', () => ({
  get: jest.fn(() => Promise.resolve({ data: { data: 'mock data' } }))
}));

test('testing RECEIVE_DATA async action', async () => {
  const dispatch = jest.fn();
  await fetchData()(dispatch);
  expect(Api.get).toHaveBeenCalledWith('foo');  // Success!
  expect(dispatch).toHaveBeenCalledWith({
    type: 'RECEIVE_DATA',
    data: 'mock data'
  });  // Success!
});

... или вы можете автоматически смоделировать api.js и ввести возвращаемое значение для Api.get:

import { fetchData } from './sampleAction';
import Api from './api';

jest.mock('./api');  // <= auto-mock
Api.get.mockResolvedValue({ data: { data: 'mock data' } });

test('testing RECEIVE_DATA async action', async () => {
  const dispatch = jest.fn();
  await fetchData()(dispatch);
  expect(Api.get).toHaveBeenCalledWith('foo');  // Success!
  expect(dispatch).toHaveBeenCalledWith({
    type: 'RECEIVE_DATA',
    data: 'mock data'
  });  // Success!
});

... или вы можете создать ручной макет на ./__mocks__/api.js :

export default {
  get: jest.fn(() => Promise.resolve({ data: { data: 'mock data' } }))
}

... и активируйте его в своем тесте следующим образом:

import { fetchData } from './sampleAction';
import Api from './api';

jest.mock('./api');  // <= activate manual mock

test('testing RECEIVE_DATA async action', async () => {
  const dispatch = jest.fn();
  await fetchData()(dispatch);
  expect(Api.get).toHaveBeenCalledWith('foo');  // Success!
  expect(dispatch).toHaveBeenCalledWith({
    type: 'RECEIVE_DATA',
    data: 'mock data'
  });  // Success!
});
person Brian Adams    schedule 15.04.2019
comment
Спасибо, @ brian-live-outdoors, это потрясающе! - person Jimmy; 16.04.2019