Search code examples
vuejs2jestjsmockingstateaction

Cannot read property state


I try to test this action:

const getGameList = function(context) {
  if(context.state.user.id){
    let request_body = {
        user_id : context.state.user.id
    }
    axios.post(`api/game_list_of_user`,request_body).then(response => {
      context.commit('UpdateGameList',response.data);
    }).catch(error => console.log(error));
  }
};

My action is to get the list of game for a specific user. This action has:

  • as input my user id .
  • as output my game of list.

My test:

import actions from '@/store/actions'
import state from '@/store/state'
import store from '@/store'
import axios from 'axios'

jest.mock('axios');

describe('getGameList', () => {
  test('Success: should return the game list of the user and update gameList in the store', () => {
    
    const state = { user: {id: 1} };
    const mockFunction = jest.fn();
    const response = {
      data: [ 
        { id:1, name:"game_name1" },
        { id:2, name:"game_name2" }
      ]
    };

    axios.post.mockResolvedValue(response);

    actions.getGameList({ mockFunction },{ state });

    //expect(mockFunction).toHaveBeenCalledTimes(1);
    //expect(mockFunction).toHaveBeenCalledWith('UpdateGameList',response.data);

  });

  test('Error: an error occurred', () => {
    const errorMessage = 'Error';
    axios.get.mockImplementationOnce(() =>
      Promise.reject(new Error(errorMessage))
    );
  });

});
  1. I declare my state (with my user id).
  2. I declare my expected response from my request (the game list = response.data).
  3. I use jest.fn() to mock the function. (Should I do that ?)

I got this error: enter image description here

I want to check:

  • My request has been called
  • The response of my request matches with my expected response
  • My mutation is then called

How can I solve that error?

Edit1: my test

jest.mock('axios');

describe('getGameList', () => {
  test('Success: should return the game list of the user and update gameList in the store', () => {
    
    const context = {
      state : { 
        user: {
          id: 1
        } 
      }
    };
    const mockFunction = jest.fn();
    const response = {
      data: [ 
        { id:1, name:"game_name1" },
        { id:2, name:"game_name2" }
      ]
    };

    axios.post.mockResolvedValue(response);

    actions.getGameList({ mockFunction, context });

    expect({ mockFunction, context }).toHaveBeenCalledTimes(1);
    expect(mockFunction).toHaveBeenCalledWith('UpdateGameList',response.data);

  });

  test('Error: an error occurred', () => {
    const errorMessage = 'Error';
    axios.get.mockImplementationOnce(() =>
      Promise.reject(new Error(errorMessage))
    );
  });
});

Solution

  • this is my solution:

    import actions from '@/store/actions'
    import mutations from '@/store/mutations'
    import state from '@/store/state'
    import store from '@/store'
    import axios from 'axios'
    
    let url = ''
    let body = {}
    
    jest.mock("axios", () => ({
      post: jest.fn((_url, _body) => { 
        return new Promise((resolve) => {
          url = _url
          body = _body
          resolve(true)
        })
      })
    }))
    
    //https://medium.com/techfides/a-beginner-friendly-guide-to-unit-testing-the-vue-js-application-28fc049d0c78
    //https://www.robinwieruch.de/axios-jest
    //https://lmiller1990.github.io/vue-testing-handbook/vuex-actions.html#testing-actions
    describe('getGameList', () => {
      test('Success: should return the game list of the user and update gameList in the store', async () => {
        const context= {
          state: {
            user: {
              id:1
            }
          },
          commit: jest.fn()
        }
        const response = {
          data: [ 
            { id:1, name:"game_name1" },
            { id:2, name:"game_name2" }
          ]
        };
    
        axios.post.mockResolvedValue(response) //OR axios.post.mockImplementationOnce(() => Promise.resolve(response));
        await actions.getGameList(context)
        expect(axios.post).toHaveBeenCalledWith("api/game_list_of_user",{"user_id":1});
        expect(axios.post).toHaveBeenCalledTimes(1)
        expect(context.commit).toHaveBeenCalledWith("UpdateGameList", response.data)
    
      });
    
      test('Error: an error occurred', () => {
        const errorMessage = 'Error';
        axios.post.mockImplementationOnce(() =>
          Promise.reject(new Error(errorMessage))
        );
      });
    
    });