Vue 测试工具。 .vue 文件中使用了模拟 vuex,但 .ts 文件中使用了原始 vuex

Posted

技术标签:

【中文标题】Vue 测试工具。 .vue 文件中使用了模拟 vuex,但 .ts 文件中使用了原始 vuex【英文标题】:vue-test-utils. Mocked vuex is used in .vue file, but original vuex is used in .ts file 【发布时间】:2021-09-28 17:40:36 【问题描述】:

我正在使用 vue-test-utils 测试我的 vue 项目。

因为我的项目使用了vuex store,所以我在测试文件中mock了vuex。

问题似乎是 .vue 文件调用模拟存储而 .ts 文件调用原始存储。

这是我的代码。

transfers.test.js

...
const localVue = createLocalVue()
localVue.use(ElementUI)
localVue.use(Vuex)
localVue.component('DefaultLayout', DefaultLayout)

const store = new Vuex.Store( // Mocked store
  state: 
   transferDetailModal: false,
...
,
  mutations: 
    showTransferDetailModal (state, detailPayload)  // It makes 'transferDetailModal' true
      console.log('run2')
      state.clickedTransferDetailId = detailPayload.transferId
...

  const wrapper = mount(Transfers,  // Mount component using mock store
    localVue,
    store,
    mocks: 
...

  describe('TransferDetailModal', () => 
    test('open and close', async () => 
      expect(wrapper.find('.transfer_id_column button').exists()).toBe(true)
      wrapper.find('.transfer_id_column button').trigger('click') // It calls mutation.
      await nextTick()

      console.log(wrapper.vm.getTransferDetailModal)
      // It logs getter of 'transferDetailModal', and false.
    )

TransferState.ts(vuex store的模块)

...

export const transfersStore: Module<TransfersState, RootState> =  // Original vuex store
  state: 
...
,
  mutations: 
    showTransferDetailModal (state, detailPayload:  transferId: string, remittanceList: Array<Remittance> ) 
      console.log('run1')
      state.clickedTransferDetailId = detailPayload.transferId
...

Transfers.vue

...
export default class Transfers extends Vue 
  @Getter getTextObjectStatus: any
  @Getter getTransferDetailModal: any // @Getter is the expression of vue-property-decorator
...

TransfersPresentation.ts

...
callback: () => 
          store.commit('showTransferDetailModal',  transferId: remittance.id, remittanceList: this.remittanceList ) // It makes transferDetailModal true
          console.log(store.getters.getTransferDetailModal) // It logs true
        
...

过程是

    在测试中点击 wrapper.find('.transfer_id_column button') 时调用 TransferPresentation 的回调。

    在回调中提交使“transferDetailModal”为真。但是'run1'被记录了,这意味着原始vuex存储的突变被称为不是模拟存储的那个。

    TransferPresentation 中的

    console.log(store.getters.getTransferDetailModal) 也将其记录为 true。意思是原始store的getter是get。

    但是,测试文件中的 console.log(wrapper.vm.getTransferDetailModal) 仍然将其记录为 false。这意味着它仍然会得到一个 mocked Store 的 getter。 (当我将模拟商店的值更改为 true 进行测试时,它会记录为 true)

那么我怎样才能让 TransferPresentation(.ts 文件)中的 getter 和 commit 也引用模拟存储,而不是原始存储?

【问题讨论】:

【参考方案1】:

我只是通过不模拟 vuex 存储,而是使用下面的原始存储解决了这个问题。

index.ts

Vue.use(Vuex)
...
const store: StoreOptions<RootState> = 
  state: 
    ...
  ,
  mutations: 
    ...
  ,
  actions: ,
  modules: 
    ...
  ,
  getters: 


export default new Vuex.Store<RootState>(store)

transfers.test.js

...
import indexStore from '../../store/index'
...
const localVue = createLocalVue()
...
localVue.use(Vuex)
...
const store = indexStore

describe('With params: all', () => 
  ...
  const wrapper = mount(Transfers, 
    localVue,
    store,
  ...

【讨论】:

【参考方案2】:

更准确地说,您不是在模拟商店,您使用的是真实商店,而是您在测试文件中创建的商店。 如果你想mock 你应该删除你的store 对象,并在调用mock 属性时将所有Vuex store 逻辑包含在mount 中,例如:

const wrapper = mount(Transfers,  
    mocks: 
      $store: 
        getters: 
          // your getters
        ,
        actions: 
          // your actions
        ,
      
   
);

如果您想继续测试您已经开始的方式,问题可能实际上是您在安装组件之前没有调用localVue.use(Vuex),至少您没有在提供的代码中显示该行。

【讨论】:

以上是关于Vue 测试工具。 .vue 文件中使用了模拟 vuex,但 .ts 文件中使用了原始 vuex的主要内容,如果未能解决你的问题,请参考以下文章

在 vue-multiselect 中测试 vuex 操作时调用了 Jest 预期的模拟函数

vue中div模拟文本编辑器并且实现v-model功能

在 Vue 3 的 Jest 测试中模拟 vue-router 的 useRoute()

Vue,vuex:如何使用命名空间存储和模拟对组件进行单元测试?

Vue 模板中的函数调用测试仅在使用括号调用函数时通过

如何在单元测试期间使用 vue-test-utils 和 jest 模拟 mixin?