I am writing tests for some async actions however the tests are failing because the type
which is returned is always REQUEST_PENDING
. So even for the tests when the data is fetched the type does not change and the test fails. I am not sure what I am doing wrong.
So the REQUEST_SUCCESS
and REQUEST_FAILED
are the tests that are always returning REQUEST_PENDING
This is my actions.js
import axios from 'axios';
import {
REQUEST_PENDING,
REQUEST_SUCCESS,
REQUEST_FAILED,
} from './constants';
export const setSearchField = (payload) => ({ type: SEARCH_EVENT, payload });
export const requestRobots = () => {
return async (dispatch) => {
dispatch({
type: REQUEST_PENDING,
});
try {
const result = await axios.get('//jsonplaceholder.typicode.com/users');
dispatch({ type: REQUEST_SUCCESS, payload: result.data });
} catch (error) {
dispatch({ type: REQUEST_FAILED, payload: error });
}
};
};
and this is my actions.test.js
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import {
REQUEST_PENDING,
REQUEST_SUCCESS,
REQUEST_FAILED,
} from './constants';
import * as actions from './actions';
const mock = new MockAdapter(axios);
const mockStore = configureMockStore([thunk]);
const payload = [
{
id: 1,
name: 'robocop',
email: '[email protected]',
key: 1,
},
];
describe('handles requestRobots', () => {
beforeEach(() => {
// Runs before each test in the suite
store.clearActions();
});
const store = mockStore();
store.dispatch(actions.requestRobots());
const action = store.getActions();
it('Should return REQUEST_PENDING action', () => {
expect(action[0]).toEqual({
type: REQUEST_PENDING,
});
});
it('Should return REQUEST_SUCCESS action', () => {
mock.onGet('//jsonplaceholder.typicode.com/users').reply(200, {
data: payload,
});
return store.dispatch(actions.requestRobots()).then(() => {
const expectedActions = [
{
type: REQUEST_SUCCESS,
payload: {
data: payload,
},
},
];
expect(store.getActions()).toEqual(expectedActions);
});
});
it('Should return REQUEST_FAILURE action', () => {
mock.onGet('//jsonplaceholder.typicod.com/users').reply(400, {
data: payload,
});
return store.dispatch(actions.requestRobots()).then(() => {
const expectedActions = [
{
type: REQUEST_FAILED,
payload: {
data: ['Error: Request failed with status code 404'],
},
},
];
expect(store.getActions()).toEqual(expectedActions);
});
});
});
The lifecycle of a thunk action is that it will dispatch the
REQUEST_PENDING
action at the start of every call and then dispatch aREQUEST_FAILED
orREQUEST_SUCCESS
action at the end.In your second and third test cases, the
store.getActions()
array actually has two elements: the pending action and the results action. You need toexpect
that the actions is an array with both. TheREQUEST_FAILED
andREQUEST_SUCCESS
actions are there, but you aren't seeing them because they are the second element.Define your
pendingAction
as a variable since you'll need it in all three tests.Then include it in your
expectedActions
array.This will cause your success test to pass. I did a quick run of the tests and the failure test still fails because it is not properly mocking the API failure. Right now it is returning a success because the
requestRobots
function uses the real axios object and not the mock axios adapter. But maybe something in your environment handles this differently.