Проверка Vue, если действие вызывает другое действие с spyOn

В Vue я хочу проверить, правильно ли действие в моем магазине вызывает другое действие, используя Jest's 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.

У меня есть другие места, где я хочу протестировать такого рода интеграцию (действие, вызывающее другое), но это все равно дает мне эту ошибку.

2 ответа

Решение

Протестируйте только ваш код, а не vuex

Проблема с такого рода тестами заключается в том, что вы тестируете, что vuex работает как положено, что, вероятно, бесполезно.

Вместо того, чтобы шпионить прямо на 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 есть хорошее руководство по этому вопросу.

Когда вы пытаетесь проверить async функция, которую вы должны использовать await

const getAsyncWithSpyOn = spyOn(actions, 'getRecipe');
expect(await getAsyncWithSpyOn()).toHaveBeenCalledTimes(3)
Другие вопросы по тегам