I'm hoping that I could ask for some help on how to test a Redux Action that involves a login API call. 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.
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.
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.
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!
Note: Elsewhere for other tests I'm using, redux-mock-store, enzyme, 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.
Remember we are not testing the Redux Thunk middleware, instead we are only testing our Thunk Action creator.
Testing a Redux Thunk action creator which queries an API
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.
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.
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.
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'));
});
};
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.