完全掌握vue全家桶单元测试 :12. vuex 测试

77 阅读3分钟

Vuex 是 Vue.js 生态中非常重要的状态管理工具,特别适合中大型应用。它通过集中式管理状态,使得应用的状态变化更加清晰和可控。

测试 vuex 方式也是分两种

  1. 真实使用 vuex store
  2. mock 的测试方式

真实渲染一般用于比较简单的项目上,因为我们需要经常在 store 里面去 dispatch 一些副作用,如果真实渲染,会有异步、数据等影响.

只要你学会了测试 vue-router,那测试 vuex 就是顺手的事情。下面来看例子。

真实使用 vuex store

来看一个简单的例子

// store.ts
import type { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'

export interface State {
  count: number
}

export const key: InjectionKey<Store<State>> = Symbol()

export const store = createStore<State>({
  state: {
    count: 0
  },
  mutations: {
    increment(state: any) {
      state.count += 1
    }
  }
})

// 定义自己的 `useStore` 组合式函数
export function useStore() {
  return baseUseStore(key)
}


测试的时候有两种 mount 方式 注入 store ,一种是 plugins 注入,一种是 provide 的方式,功能都一样,我这边推荐 plugins

  const wrapper = mount(Store, {
      global: {
        provide: {
          [key]: store
        }
      }
    })
    const wrapper = mount(Store, {
      global: {
        plugins: [[store, key]]
      }
    })

测试 store 本身逻辑是否正常

因为 store 就是一个函数,测试数据正常,就只需要调用这个对象暴露的方法

 it('测试 store 本身数据是否正常', async () => {
    expect(store.state.count).toBe(0)
    store.commit('increment')
    expect(store.state.count).toBe(1)
    store.commit('increment')
    expect(store.state.count).toBe(2)
  })

测试 store 组件内数据渲染

我们先来写一个简单的组件,逻辑就是计时器 +1

//src/components/10/StoreApp.vue
<script setup lang="ts">
import { useStore } from './store'
const store = useStore()
console.log('store', store)

</script>

<template>
  <div class="store-bg">
    下面是 vuex useStore
    <button data-testid="account-button" @click="store.commit('increment')">++按钮</button>
    数字:{{ store.state.count }}
  </div>
</template>

<style scoped>
.store-bg {
  background-color: rgb(255, 237, 203);
}
</style>

测试的逻辑就是,点击之后,触发 action,页面上渲染的数字从 0 变成 1

  it('测试 store 组件内数据渲染', async () => {
    const wrapper = mount(Store, {
      global: {
        plugins: [[store, key]]
      }
    })
    expect(wrapper.html()).toContain(0)
    await wrapper.find('[data-testid="account-button"]').trigger('click')
    expect(wrapper.html()).toContain(1)
  })

mock vuex

mock store,我们可以通过前面学到的 mock 模块方法,来 mock useStore,直接来 mock 一个 store 文件里面的 useStore 和 commit 方法


import { mount } from '@vue/test-utils'
import Store from './Store.vue'
const commit = vi.fn()

vi.mock('./store.ts', async () => {
  return {
    ...((await vi.importActual('./store.ts')) as any),
    useStore: () => ({
      state: {
        count: 0
      },
      commit: commit
    })
  }
})

describe('真实测试 vuex ', () => {
  it('测试 store 组件内数据渲染', async () => {
    const wrapper = mount(Store)
    console.log('wrapper.html()', wrapper.html())
    expect(wrapper.html()).toContain(0)
    await wrapper.find('[data-testid="account-button"]').trigger('click')
    expect(commit).toHaveBeenCalled()
    expect(commit).toHaveBeenCalledWith('increment')
  })
})

mock vuex 的方式很像 vue-router, 本质来说 vuex、vue-router都是挂到插件上,其实就是一个函数,我们只要回顾我们在 mock 那一章节 如何 mock 模块中部分函数的做法,就可以了

课件地址

上面的代码,都放到了 github 上,创作不易,免费的同时希望大家点赞收藏给我动力,我会持续更新代码和文章,消息窗口我,或者直接加我 wechat: match124

往期文章

完全掌握vue全家桶单元测试 : 1. 为什么需要前端测试

完全掌握vue全家桶单元测试 : 2. 搭建 vitest 环境

完全掌握vue全家桶单元测试 : 3. vitest 用法概览

完全掌握vue全家桶单元测试 : 4.断言常用方法

完全掌握vue全家桶单元测试 : 5.组件基本测试

完全掌握vue全家桶单元测试 : 6. 深入理解组件测试

完全掌握vue全家桶单元测试 : 7. 事件处理

完全掌握vue全家桶单元测试 : 8. mock 与替身技巧大全

完全掌握vue全家桶单元测试 : 9. timer 测试

完全掌握vue全家桶单元测试 :10. 如何测试浏览器原生方法