我如何测试异步反应redux调用

时间:2018-08-10 13:27:44

标签: reactjs react-redux jestjs

我正在尝试测试登录用户的操作,但是我总是为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())
    });
});

1 个答案:

答案 0 :(得分:0)

似乎首先需要传递调度才能创建一个接受用户并使用调度进行响应的函数:

// ---- 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'
    });
  });
});