I have an action:
export const GetChatList = userStatus => {
return dispatch => {
dispatch({
type: MessagesActionTypes.GET_MESSAGES_LIST.REQUEST,
payload: {}
});
axios
.get(config.apiUrl config.methods.getMessagesList, { params: { accountType: userStatus } })
.then(res => {
dispatch({
type: MessagesActionTypes.GET_MESSAGES_LIST.SUCCESS,
payload: res.data
});
})
.catch(err => {
dispatch({
type: MessagesActionTypes.GET_MESSAGES_LIST.ERROR,
payload: 'error text'
});
});
};
};
And I tried to write a test for this action:
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
describe('Messages actions', () => {
afterEach(() => {
fetchMock.restore();
});
it('GetChatList', () => {
fetchMock.get(config.apiUrl config.methods.getMessagesList, { params: { accountType: 1 } });
const expectedActions = [
{ type: MessagesActionTypes.GET_MESSAGES_LIST.REQUEST },
{
type: MessagesActionTypes.GET_MESSAGES_LIST.SUCCESS,
payload: ...somePayload
},
{
type: MessagesActionTypes.GET_MESSAGES_LIST.ERROR,
payload: 'error text'
}
];
const store = mockStore({...initialState});
return store.dispatch(GetChatList(1)).then(() => expect(store.getActions()).toEqual(expectedActions));
});
});
And then I get an error: TypeError: Cannot read property 'then' of undefined Why is this happening and how to properly test this action? What are my mistakes?
CodePudding user response:
fetch-mock
mocks HTTP requests made usingfetch
. But you are usingaxios
.You should return the promise created by
axios.get()
in the thunk. So that you can callstore.dispatch(GetChatList(1)).then()
method.You can use
jest.spyOn(axios, 'get')
to mockaxios.get()
method and its resolved/rejected value.
E.g.
thunk.ts
:
import axios from 'axios';
export const MessagesActionTypes = {
GET_MESSAGES_LIST: {
REQUEST: 'REQUEST',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
},
};
const config = {
apiUrl: 'http://localhost:8080/v1/api',
methods: {
getMessagesList: '/messages',
},
};
export const GetChatList = (userStatus) => {
return (dispatch) => {
dispatch({ type: MessagesActionTypes.GET_MESSAGES_LIST.REQUEST, payload: {} });
return axios
.get(config.apiUrl config.methods.getMessagesList, { params: { accountType: userStatus } })
.then((res) => dispatch({ type: MessagesActionTypes.GET_MESSAGES_LIST.SUCCESS, payload: res.data }))
.catch((err) => dispatch({ type: MessagesActionTypes.GET_MESSAGES_LIST.ERROR, payload: 'error text' }));
};
};
thunk.test.ts
:
import { GetChatList, MessagesActionTypes } from './thunk';
import configureStore from 'redux-mock-store';
import thunk, { ThunkDispatch } from 'redux-thunk';
import { AnyAction } from 'redux';
import axios from 'axios';
interface AppState {}
type DispatchExts = ThunkDispatch<AppState, void, AnyAction>;
const mws = [thunk];
const mockStore = configureStore<AppState, DispatchExts>(mws);
describe('71296970', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('should pass', () => {
jest.spyOn(axios, 'get').mockResolvedValue({ data: 'fake data' });
const store = mockStore({});
const expectedActions = [
{ type: MessagesActionTypes.GET_MESSAGES_LIST.REQUEST, payload: {} },
{ type: MessagesActionTypes.GET_MESSAGES_LIST.SUCCESS, payload: 'fake data' },
];
return store.dispatch(GetChatList(1)).then(() => {
const actions = store.getActions();
expect(actions).toEqual(expectedActions);
});
});
});
Test result:
PASS stackoverflow/71296970/thunk.test.ts
71296970
✓ should pass (5 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
thunk.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.383 s