javascript - Vue,Vuex : how to unit test a component with namespaced store and mocking?

标签 javascript vue.js vuex vuetify.js vue-test-utils

我正在使用 vue、vuex 和 vuetify 构建登录组件。我决定在商店中使用命名空间身份验证模块,这导致了我的问题。

我正在使用 TDD 来解决这个问题。我的 e2e 测试有效。但是我编写了这个单元测试(使用 mockStore),它应该只验证一个正确的 Action 已经被调度:

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 ,那么我得到的调度 Action 名称没有命名空间(duh)并且测试失败:
    - Expected
    + Received

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

实际上,我可以通过如下映射操作来修复它:
...mapActions({ login: `auth/${LOGIN}` })

但我真的更喜欢使用命名空间版本,因为当我有更多操作时它会变得丑陋。

我正在查看 vuex 源代码,尝试访问 _modulesNamespaceMap 时失败但这对我来说太复杂了。

测试这个的最佳方法是什么?我现在应该放弃 mock 并使用真正的商店吗?

完整项目可用here与此问题相关的提交是 4a7e749d4

最佳答案

建立 the example on the vue-test-utils docs ,我认为这应该工作:

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

关于javascript - Vue,Vuex : how to unit test a component with namespaced store and mocking?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61431258/

相关文章:

javascript - 在 JavaScript 中从字符串数组中创建分组对象

javascript - 应用程序初始化时无法从 localStorage 初始化存储

java - 如何将参数从 servlet 传递到 JavaScript

javascript - 如何在 npm 项目中找到 node-gyp 依赖项(..或任何依赖项)

javascript - 根据 HTML/CSS 中的条件在一些表格元素周围绘制一个框

javascript - 如何为js变量设置最小和最大边界?

javascript - Vue.js Battle - 确认框覆盖重置功能

vue.js 条件渲染一个属性

vue.js - Nuxt JS 插件是否可以只运行一次?

javascript - 如何防止Vue多次加载数据?