测试Redux登录操作

时间:2016-12-19 11:30:21

标签: javascript unit-testing testing redux

我希望我可以就如何测试涉及登录API调用的Redux Action寻求帮助。我已经看过一些测试异步Action的示例,但我还没有考虑如何测试下面的代码。

作为一个起点,我想测试a)AUTH_USER如果.post请求返回200 and b) localStorage`包含来自API调用的令牌,则调用{。}}。 p>

我已经考虑使用redux-mock-storefetch-mockisomorphic-fetch来模拟API调用,以确保我始终收到预期的API响应,但我没有想知道从哪里开始测试。

任何帮助都会在测试的起点上受到高度赞赏!即使只是测试200将返回AUTH_USER的一些帮助也会受到赞赏!

注意:在其他地方进行其他测试我会使用,redux-mock-store,酶,chai,expect,fetch-mock,isomorphic-fetch

import axios from 'axios';
import { browserHistory } from 'react-router';
import { API_URL } from 'config';
import {
  AUTH_USER
} from './types';

export function loginUser({ email, password }) {
  return function (dispatch) {
    axios.post(`${API_URL}/auth/login`, { email, password })
      .then((response) => {
        dispatch({ type: AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/feature');
      })
      .catch(() => {
        dispatch(authError('Bad Login Info'));
      });
  };
}

1 个答案:

答案 0 :(得分:2)

异步测试动机

如果登录失败,我们希望确保我们的redux thunk中间件调度AUTHENTICATION_SUCCESS操作,如果登录成功AUTHENTICATION_FAILED操作。

请记住,我们不是在测试Redux Thunk中间件,而只是测试我们的Thunk Action创建者。

测试查询API的Redux Thunk操作创建器

  1. 使用redux-thunk中间件
  2. 为每个单元测试创​​建一个模拟存储
  3. 使用模拟库(如nock)拦截http请求,以测试为给定类型的请求调度哪些操作。由于我们正在测试登录请求,因此这里的明显案例是http响应,表示登录成功和失败。
  4. 验证是否已针对给定的http响应将正确的操作分派给商店。
  5. 示例

    测试

    以下是使用nock模拟api调用和expect库以进行测试断言的两次登录成功和失败测试的示例。

    import configureMockStore from 'redux-mock-store'
    import thunk from 'redux-thunk'
    import nock from 'nock'
    import expect from 'expect' // You can use any testing library
    
    // modify these imports to suit your project
    import * as actions from '../../actions/TodoActions' 
    import * as types from '../../constants/ActionTypes'
    
    import {
      AUTH_USER, AUTH_ERROR
    } from './types';
    
    const API_URL = 'www.api-example.com'
    const middlewares = [ thunk ]
    const mockStore = configureMockStore(middlewares)
    
    describe('async actions', () => {
      afterEach(() => {
        nock.cleanAll()
      })
    
      it('creates AUTH_USER action when user is logged in', () => {
        nock(API_URL)
          .post(/auth/login)
          .reply(200, { data: 'Logged in successfully'] }})
    
        const expectedActions = [
          { type: AUTH_USER }
        ]
        const store = mockStore({ })
    
        return store.dispatch(actions.loginUser({'example@x.com','password'}))
          .then(() => { // return of async actions
            expect(store.getActions()).toEqual(expectedActions)
          })
      })
    
      it('creates AUTH_ERROR if user login fails', () => {
        nock(API_URL)
          .post(/auth/login)
          .reply(404, { data: {error: 404 }] }})
    
        const expectedActions = [
          { type: AUTH_ERROR }
        ]
        const store = mockStore({ })
    
        return store.dispatch(actions.loginUser({'example@x.com','password'}))
          .then(() => { // return of async actions
            expect(store.getActions()).toEqual(expectedActions)
          })
      })
    })
    

    现在要使示例工作,您需要在thunk动作创建者返回的函数内添加一个return语句。

    通过最终返回axios.post给我们的承诺,我们可以在我们的测试中添加.then调用,以便在承诺解决之后发出已经调度了哪些动作的断言。

    Thunk action creator

    import axios from 'axios';
    import { browserHistory } from 'react-router';
    import { API_URL } from 'config';
    import {
      AUTH_USER
    } from './types';
    
    export function loginUser({ email, password }) {
      return function (dispatch) {
        return axios.post(`${API_URL}/auth/login`, { email, password })
          .then((response) => {
            dispatch({ type: AUTH_USER });
            localStorage.setItem('token', response.data.token);
            browserHistory.push('/feature');
          })
          .catch(() => {
            dispatch(authError('Bad Login Info'));
          });
      };
    }