Vue 检查动作是否使用 spyOn 调用其他动作

Vue checking if action calls other action with spyOn

在 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.

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

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

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

不是直接监视 actions,而是断言 vuex 在调用 dispatch('getRecipe', fruit) 时正确调用 getRecipe 动作,我会测试 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 的上下文中测试这些动作。

关于这个有一个很好的教程in the vue test utils documentation

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

const getAsyncWithSpyOn = spyOn(actions, 'getRecipe');
expect(await getAsyncWithSpyOn()).toHaveBeenCalledTimes(3)