0

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?

1 Answers1

1
  • fetch-mock mocks HTTP requests made using fetch. But you are using axios.

  • You should return the promise created by axios.get() in the thunk. So that you can call store.dispatch(GetChatList(1)).then() method.

  • You can use jest.spyOn(axios, 'get') to mock axios.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
Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • thanks a lot! Can you explain me how to send params in jest.spyOn('axios', get) ? – Батрадз Санакоев Mar 01 '22 at 08:58
  • @БатрадзСанакоев Please explain what you want to achieve. What do you mean by "send params"? – Lin Du Mar 01 '22 at 09:17
  • Let's rephrase, I changed the code according to your advice, but then I got an error: when a successful action is executed, my payload is undefined. I can't understand why. What are my mistakes? jest.spyOn(axios, 'get').mockResolvedValue({ id: 1, userId: 'someId', userName: 'username', text: 'text' }); const expectedActions = [....{ type: MessagesActionTypes.GET_MESSAGES_LIST.SUCCESS, payload: id: 1, userId: 'someId', userName: 'username', text: 'text' }...] – Батрадз Санакоев Mar 01 '22 at 09:25
  • I solved my problem, I forgot to write 'data' in 'mockResolvedValue' – Батрадз Санакоев Mar 01 '22 at 09:34