Search code examples
javascriptvue.jsunit-testingvuex

Vue-test-utils: How do I mock the return of an action in VueX?


I'm writing a test for a Vue component which dispatches to a module store to perform an action and use the result from it.

The action makes a call to our API so I don't want to run the test with that action, but instead mock it and return some dummy data to see that the rest of the method flow works.

So in my test I add a mock store, with a mocked action which just returns hardcoded data, with the intent to see that the component method getData() sets the response of the action to the data.

This doesn't seem to work however and instead it seems as if the real action is called. How do I set it up so that I can avoid calling the real actions and instead use the ones I create for the tests?

Component method, simplified:

methods: {
    async getData() {
        const response = this.$store.dispatch("global/getDataFromAPI")

        if (!response) return

        this.$data.data = {...response.data}
    }
}

Test code, simplified:

describe('Component.vue', () => {
  let localVue;
  let vuetify;
  let wrapper;
  let store;

  beforeEach(() => {
    localVue = createLocalVue();
    localVue.use(Vuex)
    vuetify = new Vuetify();

    let globalActions = {
      getDataFromAPI: async () => {
        return {
          status: 200,
          data: {
            information1: "ABC",
            information2: 123,
          }
        }
      } 
    }

    store = new Vuex.Store({
      modules: {
        global: {
          actions: globalActions,
          namespaced: false
        },
      }
    })

    wrapper = mount(Component, {
      localVue,
      vuetify,
      attachTo: div,
      mocks: {
        $t: () => { },
        $store: store,
      },
    });
  });

  it('Data is set correctly', async () => {
    await wrapper.vm.getData();

    const dataInformation1 = wrapper.vm.$data.data.information1;
    expect(dataInformation1).toBe("ABC")
  });

Solution

  • First, if you want to mock the Vuex Store you don't need to call localVue.use(Vuex). You should call localVue.use(Vuex) only if you are going to use real Vuex Store in test. And if you are going to you must pass store object along with localVue and another arguments, not in mocks property.

    Second, to mock your action you can mock store's dispatch method like this:

    mocks: {
      $store: {
        dispatch: () => { dummyData: 'dummyData' }
      }
    }