Как выполнить модульное тестирование вложенных действий в приложении Vue? - PullRequest
5 голосов
/ 09 апреля 2020

У меня есть проект Vue на основе TypeScript с Jest в качестве тестовой среды. У меня есть действия в модуле, которые я пытаюсь проверить.

Мои действия выглядят так:

  @Action({})
  saveSomeData (payload: any): Promise<any> {
    const { isActive, id, routes } = payload
    return this.context.dispatch('otherModule/createId', '', { root: true })
        .then((id: string) => {
          payload = { isActive, id, routes, type: 'postRoutes' }
          return this.context.dispatch('submitRoutes', payload)
        })
  }

  @Action({})
  submitRoutes (payload: any): Promise<any> {
    const { isActive, id, routes, type } = payload
    return ActiveService.setActive(id)
        .then(() => this.context.dispatch(type, { id, routes }))
  }

Вот как выглядит мой тест:

// Mocking createId in otherModule module to return ID
jest.mock('@/store/modules/otherModule', () => ({
  createId: jest.fn(() => Promise.resolve([
    {
      id: 'someId'
    }
  ]))
}))

...

describe('Testing save MyModule data', () => {
    let store: any

    beforeEach(() => {
      store = new Vuex.Store({
        modules: {
          myModule,
          otherModule
        }
      })
    })

    test('Should call createId and then call submitRoutes if ID is empty', async () => {
      const payload = {
        isActive: true,
        id: '',
        routes: []
      }
      const pld = {
        isActive: true,
        id: 'someId',
        routes: [],
        type: 'postRoutes'
      }

      store.dispatch = jest.fn()
      await store.dispatch('myModule/saveSomeData', payload)
      expect(store.dispatch).toHaveBeenCalledWith('myModule/saveSomeData', payload)
      expect(store.dispatch).toHaveBeenCalledWith('otherModule/createId') // <-- here I get an error
      expect(store.dispatch).toHaveBeenCalledWith('myModule/submitRoutes', pld)
    })
  })

Проблема: Мой тест не пройден, и я не нашел способа заставить его работать.

Ошибка:

Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: "otherModule/createId"
Received: "myModule/saveSomeData", {"id": "", "isActive": true, "routes": []}

Number of calls: 1

Что я пробовал

Я следовал документации Vuex вместе с Jest , я также пробовал разные решения из inte rnet - к сожалению, не повезло.

Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 09 апреля 2020

store.dispatch = jest.fn() делает диспетчерскую функцию недоступной, она не должна вызывать saveSomeData и, следовательно, отправлять другие действия.

Это утверждение бесполезно, поскольку оно в основном проверяет предыдущее строка:

expect(store.dispatch).toHaveBeenCalledWith('myModule/saveSomeData', payload)

store.dispatch шпион или заглушка не должны влиять на context.dispatch в действиях, поскольку контекст создается при инициализации хранилища и уже использует исходный dispatch. Это может быть ненужным, потому что это действия, которые должны быть проверены, а не сам Vuex.

Действия можно шпионить на уровне модуля с помощью jest.mock и jest.requireActual или локально на объекте модуля Vuex при необходимости , Модуль шпионов и издевательств должен происходить на высшем уровне. Шпионы и издевательства над объектами должны произойти до создания хранилища.

В этом случае проверенные юниты имеют действия myModule, ActiveService.setActive и otherModule/createId могут рассматриваться как разные юниты и должны быть имитированы. Если postRoutes содержит побочные эффекты, их также можно высмеивать.

jest.spyOn(otherModule.actions, 'createId');
jest.spyOn(ActiveService, 'setActive');
store = new Vuex.Store(...)

...

otherModule.actions.createId.mockValue(Promise.resolve('stubbedId'));
ActiveService.setActive.mockValue(Promise.resolve());
await store.dispatch('myModule/saveSomeData', payload)
// assert otherModule.actions.createId call
// assert ActiveService.setActive call
// assert otherModule.actions.postRoutes call
...