Vue, vuex: как выполнить модульное тестирование компонента с хранением пространства имен и имитацией? - PullRequest
3 голосов
/ 25 апреля 2020

Я создаю компонент входа с использованием vue, vuex и vuetify. Я решил использовать модуль аутентификации в пространстве имен в магазине, и это вызывает у меня проблему.

Я подхожу к этому, используя TDD. Мой тест e2e работает. Но я написал этот модульный тест (с использованием mockStore), который должен только проверять, что было отправлено правильное действие:

describe('Login component', () => {
  let wrapper
  const mockStore = {
    dispatch: jest.fn(),
  }

  beforeEach(() => {
    wrapper = mount(Login, {
      localVue,
      mocks: { $store: mockStore },
      computed: {
        error: () => 'test error',
      },
      data: () => ({
        valid: true
      })
    })
  })

  it('should dispatch login action', async () => {
    wrapper.find('[data-test="username"]').setValue('username')
    wrapper.find('[data-test="password"]').setValue('password')
    await wrapper.vm.$nextTick()
    await wrapper.vm.$nextTick()
    wrapper.find('[data-test="login"]').trigger('click')
    await wrapper.vm.$nextTick()
    expect(mockStore.dispatch).toHaveBeenCalledWith(
      `auth/${LOGIN}`,
      { username: 'username', password: 'password' }
    )
  })
})

Компонент использует mapActions только следующим образом:

...mapActions('auth', [LOGIN])

И кнопка, запускающая его:

      <v-btn
        color="info"
        @click="login({ username, password })"
        data-test="login"
        :disabled="!valid"
      >Login</v-btn>

Я получаю ошибку:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'auth/' of undefined"

Если я уроню пространство имен в mapActions, то отправленное действие имя, которое я получаю, не является пространством имен (duh), и тест не пройден:

    - Expected
    + Received

    - "auth/login",
    + "login",

Я на самом деле смог это исправить, сопоставив действия следующим образом:

...mapActions({ login: `auth/${LOGIN}` })

Но я бы Я действительно предпочитаю использовать версию с пространством имен, потому что это будет ужасно, когда у меня будет больше действий.

Я искал исходный код vuex, и он не работает при попытке доступа к _modulesNamespaceMap, но тогда он становится слишком сложным для меня.

Какой лучший способ проверить это? Должен ли я просто отказаться от насмешек и использовать настоящий магазин в этот момент?

Полный проект доступен здесь и коммит по этому вопросу 4a7e749d4

1 Ответ

1 голос
/ 26 апреля 2020

На основе примера на vue-test-utils документах , я думаю, это должно работать:

/* ... other imports and setup ... */
import Vuex from 'vuex'

describe('Login component', () => {
  let wrapper
  const actions = {
    login: jest.fn(),
  }
  const mockStore = new Vuex({
    modules: {
      auth: {
        namespaced: true,
        actions,
      },
    },
  })

  beforeEach(() => {
    wrapper = mount(Login, {
      localVue,
      mocks: { $store: mockStore },
      computed: {
        error: () => 'test error',
      },
      data: () => ({
        valid: true
      })
    })
  })

  it('should dispatch login action', async () => {
    wrapper.find('[data-test="username"]').setValue('username')
    wrapper.find('[data-test="password"]').setValue('password')
    await wrapper.vm.$nextTick()
    await wrapper.vm.$nextTick()
    wrapper.find('[data-test="login"]').trigger('click')
    await wrapper.vm.$nextTick()
    expect(actions.login).toHaveBeenCalled() // <-- pretty sure this will work
    expect(actions.login).toHaveBeenCalledWith({ // <-- not as sure about this one
      username: 'username',
      password: 'password',
    })
  })
})
...