vuejs / vuex

🗃️ Centralized State Management for Vue.js.
https://vuex.vuejs.org
MIT License
28.42k stars 9.57k forks source link

Deprecate testAction helper in favor of vuex-mock-store #1562

Open winniehell opened 5 years ago

winniehell commented 5 years ago

What problem does this feature solve?

The officially documented way to test actions

What does the proposed API look like?

Recommend to use https://github.com/posva/vuex-mock-store instead.

// actions.js

import shop from '../api/shop'

export const getAllProducts = ({ commit }) => {
  commit('REQUEST_PRODUCTS')
  return shop.getProducts().then(products => {
    commit('RECEIVE_PRODUCTS', products)
  })
}
// actions.spec.js

import { Store } from 'vuex-mock-store'

const store = new Store()

afterEach(() => store.reset())

describe('actions', () => {
  it('getAllProducts', done => {
    actions.getAllProducts(store)
      .then(() => {
        expect(store.commit).toHaveBeenCalledTimes(2)
        expect(store.commit).toHaveBeenCalledWith('REQUEST_PRODUCTS')
        expect(store.commit).toHaveBeenCalledWith('RECEIVE_PRODUCTS',  /* mocked response */)
      })
      .then(done)
      .catch(done.fail)
})

see also https://github.com/vuejs/vue-test-utils/issues/1060

winniehell commented 5 years ago

@posva What do you think?

posva commented 5 years ago

I think my mock doesn't cover testing actions so far. To be honest, when testing actions I always pass things manually using jest.fn() to create mocks and just see if they were called.

I was thinking of adding some kind of api to generate a context that call other actions and mutations: https://github.com/posva/vuex-mock-store/issues/9

winniehell commented 5 years ago

@posva Thanks for the fast reply! :rocket:

I think my mock doesn't cover testing actions so far.

Ignoring Vuex modules for now (which aren't supported by the existing testAction helper either), what do you think is missing? Judging from the API docs, your mock store seems to provide everything from the context apart from rootState and rootGetters which should only be relevant in the presence of Vuex modules.

I always pass things manually using jest.fn() to create mocks

Isn't that exactly what your mock store does with dispatch and commit?

posva commented 5 years ago

but the Store mock can mock the whole store so you don't care about it in components. testAction is a helper to individually test an action, which you should still do if you are mocking the whole Store

winniehell commented 5 years ago

@posva You are only advertising vuex-mock-store for unit testing components but I think it can be used to unit test actions, too, because it has all we need. :smiley:

When unit testing actions, we want to mock away the state, getters, and mutations. All of that is already supported by vuex-mock-store. :tada:

Here is a working example project: https://gitlab.com/winniehell/vue-examples/blob/master/vuex-mock-action-tests/test/store/actions.spec.js

posva commented 5 years ago

oh right, you pass the store to the action, I didn't see that! That's neat. Adding support for rootState and rootGetters could be added as well either directly on the store or with a getContext() method. Now, that I think about it, it could be useful to have o Module so modules can also be tested individually, but I need to think more about it

winniehell commented 5 years ago

Adding support for rootState and rootGetters could be added as well

@posva Do you think that is a requirement to replace the testAction helper? or can that be a second iteration?

with a getContext() method

I think such a method would be cleaner. :+1:

it could be useful to have o Module

I agree! :+1: I would be happy to help adding that to vuex-mock-store if you like.