简体   繁体   English

测试Redux登录操作

[英]Testing a Redux login Action

I'm hoping that I could ask for some help on how to test a Redux Action that involves a login API call. 我希望我能就如何测试涉及登录API调用的Redux Action寻求帮助。 I've looked at some examples of testing an async Action, but I haven't wrapped my head around how to test the code below. 我已经看过一些测试异步Action的例子,但是我还没有考虑如何测试下面的代码。

As a starting point, I would like to test that a) AUTH_USER is called if the .post request returns a 200 and b) localStorage` contains the token from the API call. 作为一个起点,我想测试a)如果.post请求返回200 and b) localStorage`包含来自API调用的令牌,则调用AUTH_USER

I've looked at using redux-mock-store , fetch-mock and isomorphic-fetch in order to mock the API calls to make sure I always receive the expected API response, but I have no idea where to start with the test. 我已经看过使用redux-mock-storefetch-mockisomorphic-fetch来模拟API调用以确保我总是收到预期的API响应,但我不知道从哪里开始测试。

Any help would be highly appreciated on a starting point for the tests! 任何帮助都将在测试的起点上受到高度赞赏! Even some help on just testing that 200 will return AUTH_USER would be appreciated! 甚至一些帮助只是测试200将返回AUTH_USER将不胜感激!

Note: Elsewhere for other tests I'm using, redux-mock-store, enzyme, chai, expect, fetch-mock, isomorphic-fetch 注意:其他我正在使用的测试,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'));
      });
  };
}

Async Test Motivation 异步测试动机

We want to ensure that a AUTHENTICATION_SUCCESS action is dispatched by our redux thunk middleware if the login is successful a AUTHENTICATION_FAILED action if the log in fails. 我们希望确保如果登录失败,如果登录成功AUTHENTICATION_FAILED操作,则我们的redux thunk中间件将调度AUTHENTICATION_SUCCESS操作。

Remember we are not testing the Redux Thunk middleware, instead we are only testing our Thunk Action creator. 请记住,我们不是在测试Redux Thunk中间件,而只是测试我们的Thunk Action创建者。

Testing a Redux Thunk action creator which queries an API 测试查询API的Redux Thunk动作创建者

  1. Create a mock store for each unit test with redux-thunk middleware 使用redux-thunk中间件为每个单元测试创​​建一个模拟存储
  2. Use a mocking library such as nock to intercept http requests to test which actions are dispatched for a given type of request. 使用模拟库(如nock)拦截http请求以测试为给定类型的请求调度哪些操作。 Since we are testing a login request obvious cases here are http responses signalling login success and failure. 由于我们正在测试登录请求,因此这里的明显案例是http响应,表示登录成功和失败。
  3. Verify the correct action was dispatched to the store for a given http response. 验证是否已针对给定的http响应将正确的操作分派给商店。

Example

Tests 测试

Here is an example of two tests for login success and failure using nock to mock the api call and the expect library for test assertions. 下面是使用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)
      })
  })
})

Now to make the example work you need to add a return statement inside the function returned by your thunk action creator. 现在要使示例工作,您需要在thunk动作创建者返回的函数内添加一个return语句。

By eventually returning the promise given to us by axios.post we can add the .then call inside our test to make assertions about which actions have been dispatched after the promise has resolved. 通过最终返回axios.post给我们的承诺,我们可以在我们的测试中添加.then调用,以便在promise解决调用已分派的操作。

Thunk action creator Thunk行动创造者

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM