In Vue, I want to check if an action in my store is correctly calling another action using Jest's spyOn
, I tried it different ways but it doesn't seem to work, here's my code:
// index.js
getRecipes ({ dispatch }) {
const fruits = ['apple', 'banana', 'pear']
fruits.forEach((fruit) => {
dispatch('getRecipe', fruit)
})
},
async getRecipe ({ commit }) {
const recipe = await recipesService.fetchRecipe(payload)
commit(SET_RECIPE, { recipe })
},
// index.spec.js
test('getRecipes calls getRecipe 3 times, each with the right fruit', () => {
const commit = jest.fn()
const dispatch = jest.fn()
const spy = spyOn(actions, 'getRecipe')
const result = actions.getRecipes({ commit, dispatch })
expect(spy).toHaveBeenCalledTimes(3)
expect(spy).toHaveBeenCalledWith('apple')
})
But when I run the tests, this is the output I get:
Expected spy to have been called three times, but it was called zero times.
I have other places where I want to test these kind of integrations (an action calling another one), but it still gives me this error.
The problem with this kind of test, is that you're testing that vuex works as expected, which is probably worthless.
Instead of spy directly on the actions
, and assert that vuex correctly calls the getRecipe
action when dispatch('getRecipe', fruit)
is called, I would test just that the getRecipes
action calls dispatch
properly:
test('getRecipes dispatches 3 "getRecipe" actions, each with the right fruit', () => {
const commit = jest.fn()
const dispatch = jest.fn()
const result = actions.getRecipes({ commit, dispatch })
expect(dispatch).toHaveBeenCalledTimes(3)
expect(dispatch.mock.calls[0][0]).toBe('apple')
expect(dispatch.mock.calls[1][0]).toBe('banana')
expect(dispatch.mock.calls[2][0]).toBe('pear')
})
You're not really showing how you're importing and exporting the modules, but I guess in your code, the actions file exports just a plain object with the actions, and the test just imports it.
In your application code, it's likely that a you're adding those actions to vuex, then loading vuex into your app with:
new Vue({store})
So, in your tests, the actions
module really does not know anything about vuex itself (here I'm guessing really, can't really tell from your published code but it's likely).
That's why your tests does not work as expected, because in the test the getRecipes
method just gets a dispatch
parameter and calls it, but vuex is not really doing anything there, so there is no way that dispatch
call would invoke another action.
Now, if you want to still test this with jest, you should do it from a component, so you're testing the actions in the context of vue and vuex.
There is a good tutorial about this in the vue test utils documentation.