Вопрос по reactjs, redux, javascript, jasmine – Как выполнить модульное тестирование асинхронных действий Redux для проверки ответа Ajax

8

Я создаю промежуточное ПО для выполнения запросов AJAX с использованием асинхронных действий. Промежуточное программное обеспечение перехватывает исходное действие, выполняет запрос ajax и повторноdispatchИсходное действие вместе с ответомurl.

Итак, мой компонент будет простоdispatch подобное действие

onClick() {
    dispatch(ActionCreator.fetchUser());
}

Промежуточное ПО позаботится об остальном, как показаноВот.

У меня вопрос, что мне делать для юнит-тестирования? Должен ли я издеваться надonClick сам? или я должен написать смоделированное промежуточное ПО и отправить действия с поддельным ответом?

Я не уверен, какой подход я должен выбрать. Я старалсянесколько вещейНо ничего из того, что я пробовал, не имело для меня смысла.

Есть указатели?

Ваш Ответ

2   ответа
2

мне не нужно издеваться над какими-либо методами магазина или чем-то еще. Это так же просто, как издеваться над Ajax-запросом. я используюsuperagentвот так я это и сделал

const mockResponse = {
    body: {
        data: 'something'
    }
};

spyOn(superagent.Request.prototype, 'end').and.callFake((cb) => {
    cb(null, mockResponse); // callback with mocked response
});

// and expect it to be called
expect(superagent.Request.prototype.end).toHaveBeenCalled();
Это тоже работает. На самом деле это может быть еще проще:github.com/reactjs/redux/issues/1716 Dan Abramov
25
Примечание: ответ ниже несколько устарел.

Вот.
Вы все еще можете сделать это и другим способом, хотя.

Теперь у нас естьраздел по тестированию создателей асинхронных действий в официальных документах.

Для создателей асинхронных действий, использующихRedux Thunk или другое промежуточное ПО, лучше всего издеваться над магазином Redux для тестов. Вы все еще можете использоватьapplyMiddleware() с ложным магазином, как показано ниже. Вы также можете использоватьнатягивать тетиву высмеивать запросы HTTP.

function fetchTodosRequest() {
  return {
    type: ADD_TODOS_REQUEST
  };
}

function fetchTodosSuccess(body) {
  return {
    type: ADD_TODOS_SUCCESS,
    body
  };
}

function fetchTodosFailure(ex) {
  return {
    type: ADD_TODOS_FAILURE,
    ex
  };
}

export function fetchTodos(data) {
  return dispatch => {
    dispatch(fetchTodosRequest());
    return fetch('http://example.com/todos')
      .then(res => res.json())
      .then(json => dispatch(addTodosSuccess(json.body)))
      .catch(ex => dispatch(addTodosFailure(ex)));
  };
}

можно проверить как:

import expect from 'expect';
import { applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import * as actions from '../../actions/counter';
import * as types from '../../constants/ActionTypes';
import nock from 'nock';

const middlewares = [thunk];

/**
 * Creates a mock of Redux store with middleware.
 */
function mockStore(getState, expectedActions, onLastAction) {
  if (!Array.isArray(expectedActions)) {
    throw new Error('expectedActions should be an array of expected actions.');
  }
  if (typeof onLastAction !== 'undefined' && typeof onLastAction !== 'function') {
    throw new Error('onLastAction should either be undefined or function.');
  }

  function mockStoreWithoutMiddleware() {
    return {
      getState() {
        return typeof getState === 'function' ?
          getState() :
          getState;
      },

      dispatch(action) {
        const expectedAction = expectedActions.shift();
        expect(action).toEqual(expectedAction);
        if (onLastAction && !expectedActions.length) {
          onLastAction();
        }
        return action;
      }
    }
  }

  const mockStoreWithMiddleware = applyMiddleware(
    ...middlewares
  )(mockStoreWithoutMiddleware);

  return mockStoreWithMiddleware();
}

describe('async actions', () => {
  afterEach(() => {
    nock.cleanAll();
  });

  it('creates FETCH_TODO_SUCCESS when fetching todos has been done', (done) => {
    nock('http://example.com/')
      .get('/todos')
      .reply(200, { todos: ['do something'] });

    const expectedActions = [
      { type: types.FETCH_TODO_REQUEST },
      { type: types.FETCH_TODO_SUCCESS, body: { todos: ['do something']  } }
    ]
    const store = mockStore({ todos: [] }, expectedActions, done);
    store.dispatch(actions.fetchTodos());
  });
});
Что за «выборка» здесь? Max P
Есть ли пример или документ, чтобы сделать тест с дополнительным аргументом redux thunk? Это меня смущает Alessander França

Похожие вопросы