Как я могу протестировать вызов async react redux

Я пытаюсь проверить действия пользователя, входящего в систему, но всегда получаю пустой массив для моего store.getActions(). Как я могу протестировать функцию входа в систему, чтобы получить тип действия SET_USER, если оно выполнено успешно, или ОШИБКА, если нет. Вот мой код для действий аутентификации

export const loginUser = (user) => dispatch => {
axios
    .post('http://localhost:5000/users/login', user)
    .then(res => {

        dispatch({
            type: 'SET_USER',
            payload: res.data
        })
    })
    .catch(err => 
        dispatch({
            type: 'ERROR',
            payload: err.response
          })
    );
};

и здесь для проверки действий аутентификации

import { loginUser } from '../../actions/authActions';

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe('Auth actions', () => {
    const user = {
        email: 'user@test.com',
        password: '123456',
    }

    let store;
    beforeEach(() => {
      store = mockStore();
    });

    it('should login user', () => {
        store.dispatch(loginUser())
       console.log(store.getActions())
    });
});
0
0
64
1

Ответы 1

Похоже, что сначала нужно передать отправку, чтобы создать функцию, которая принимает пользователя и отвечает, используя отправку:

// ---- authActions.js ----
import axios from 'axios';

export const loginUser = dispatch => user => {
  axios
      .post('http://localhost:5000/users/login', user)
      .then(res => {

          dispatch({
              type: 'SET_USER',
              payload: res.data
          })
      })
      .catch(err => 
          dispatch({
              type: 'ERROR',
              payload: err.response
            })
      );
  };

Чтобы протестировать его, вам нужно смоделировать axios.post() и создать макет, который будет передаваться как dispatch. Вам нужно будет сделать тестовые функции async и приостановить их, чтобы позволить обратным вызовам выполняться. В целом тест выглядит так:

// ---- authActions.test.js ----
import axios from 'axios';
import { loginUser } from '../../actions/authActions';

describe('Auth actions', () => {

  const user = {
    email: 'user@test.com',
    password: '123456',
  }

  let postMock;
  let dispatchMock;

  beforeEach(() => {
    postMock = jest.spyOn(axios, 'post');
    postMock.mockImplementation((url, u) => {
      if (u === user) {
        return Promise.resolve({ data: 'mocked response' });
      }
      else {
        return Promise.reject({ response: 'login failed' });
      }
    });
    dispatchMock = jest.fn();
  });

  afterEach(() => {
    postMock.mockRestore();
  });

  it('should login user', async () => {
    loginUser(dispatchMock)(user);
    // Pause the synchronous test here to let the event loop cycle
    await Promise.resolve();

    expect(dispatchMock).toHaveBeenCalledTimes(1);
    expect(dispatchMock).toHaveBeenCalledWith({
      type: 'SET_USER',
      payload: 'mocked response'
    });
  });

  it('should return error', async () => {
    loginUser(dispatchMock)({ email: 'something', password: 'invalid' });
    // Allow two event loop cycles for the catch to execute
    await Promise.resolve().then();

    expect(dispatchMock).toHaveBeenCalledTimes(1);
    expect(dispatchMock).toHaveBeenCalledWith({
      type: 'ERROR',
      payload: 'login failed'
    });
  });
});

Спасибо, но я всегда получаю тип действия ERROR с полезной нагрузкой undefined.

Dalies 11.08.2018 15:01

@Dalies Я только что понял, что вам, вероятно, сначала следует пройти dispatch, поэтому я обновил свой ответ, указав рекомендуемое изменение кода и функциональный тест

Brian Adams 11.08.2018 17:29

Напоминание @Dalies о том, что нужно проголосовать и пометить как принятый, если ответ содержит необходимую информацию. Если у вас возникнут дополнительные вопросы, дайте нам знать

Brian Adams 13.08.2018 17:13

Другие вопросы по теме