5

在 Vue 中,我想检查我的商店中的一个动作是否正确地使用 Jest 调用另一个动作spyOn,我尝试了不同的方式,但它似乎不起作用,这是我的代码:

// 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')
})

但是当我运行测试时,这是我得到的输出:

Expected spy to have been called three times, but it was called zero times.

我还有其他地方想测试这种集成(一个动作调用另一个),但它仍然给我这个错误。

4

2 回答 2

8

只测试你的代码,而不是 vuex 的

这种测试的问题在于,您正在测试 vuex 是否按预期工作,这可能毫无价值。

我不会直接在 spy 上进行监视actions,并断言 vuex在被调用getRecipe时正确调用了该操作dispatch('getRecipe', fruit),而是仅测试该getRecipes操作dispatch是否正确调用:

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')
})

如果你还想测试 vuex 集成怎么办

您并没有真正展示如何导入和导出模块,但我猜在您的代码中,动作文件只导出一个带有动作的普通对象,而测试只是导入它。

在您的应用程序代码中,您可能会将这些操作添加到 vuex,然后将 vuex 加载到您的应用程序中:

new Vue({store})

因此,在您的测试中,该actions模块确实对 vuex 本身一无所知(这里我猜真的,不能从您发布的代码中真正分辨出来,但很可能)。

这就是为什么您的测试不能按预期工作的原因,因为在测试中该getRecipes方法只是获取一个dispatch参数并调用它,但 vuex 并没有真正在那里做任何事情,所以dispatch调用不会调用另一个动作。

现在,如果你仍然想用 jest 来测试它,你应该从一个组件中做,所以你在 vue 和 vuex 的上下文中测试动作。

在 vue test utils 文档中有一个很好的教程。

于 2018-12-07T12:16:57.010 回答
0

当您尝试测试async功能时,您需要使用await

const getAsyncWithSpyOn = spyOn(actions, 'getRecipe');
expect(await getAsyncWithSpyOn()).toHaveBeenCalledTimes(3)
于 2018-12-07T12:35:14.593 回答