vitest 是由 vite 提供支持的极速单元测试框架,VueTestUtils 是 Vue.js 的官方测试实用程序库,pinia 是 Vue.js 的状态管理库,以上均为各自官网对其的描述
项目中使用状态管理是非常常见的,所以对它也可以来个单元测试,这里我们可能会有两个场景:1. 测试在组件中使用 pinia;2. 直接测试 store
// store
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(1)
const doubleCount = computed(() => count.value * 2)
function increment() {
return count.value++
}
return { count, doubleCount, increment }
})
// component
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
function increment() {
store.increment()
}
</script>
<template>
<div>count: {{ store.count }}</div>
<button @click="increment">increment</button>
</template>
// spec | test
import { describe, test, expect, beforeEach } from 'vitest'
import { shallowMount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import HomeView from '@/views/HomeView.vue'
describe('demo1', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
test('component-pinia', async () => {
const wrapper = shallowMount(HomeView)
expect(wrapper.html()).toContain('count: 1')
await wrapper.find('button').trigger('click')
expect(wrapper.html()).toContain('count: 2')
})
})
- 第一个 demo 由三个部分组成,store、组件和测试文件
- store 里是一个常见的案例,使用了 SetupStore 的写法,与 OptionStore 相比,ref()就是
state
,computed()就是getters
,function()就是actions
,定义了一个 count,一个 count 自增的函数和计算属性双倍获取 count 值- 组件的逻辑非常简单,点击按钮,增加 store 里的 count 值,页面显示实时数字
- 测试文件中因为是在单元测试环境下,所以需要在测试代码运行之前即
beforeEach
中,显式激活 piniasetActivePinia(createPinia())
使用 test-utils 库的 shallowMount 方法浅渲染挂载组件
组件通过 html 方法返回元素的 HTML
然后使用 vitest 库的 expect 创建断言,toContain 是断言检查值是否在数组中
组件通过 find 方法返回查找元素,通过 trigger 方法触发 DOM 事件,模拟用户按下按钮的操作,按下按钮前后都断言了,会判断实际执行结果与预期结果是否一致,如果不一致则会抛出错误
第二个 demo 仍使用相同的 store 文件,只需要重新写一个测试文件
import { describe, test, expect, beforeAll } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
import { useCounterStore } from '@/store/counter'
describe('demo2', () => {
let store: any
beforeAll(() => {
setActivePinia(createPinia())
store = useCounterStore()
})
test('count', () => {
const { count } = store
expect(count).toBe(1)
})
test('doubleCount', () => {
const { doubleCount } = store
expect(doubleCount).toBe(2)
})
})
第二个测试 demo 仍是在测试代码运行前显示激活 pinia
用了两个测试组分别测试了从 store 中获取 count 和计算双倍 count 是否与预期值一致
虽然这仍是一个简单的 demo,但它还是有很多值得注意的知识点的
beforeEach
和setActivePinia
,这里使用beforeAll
也可以,它是在所有测试代码运行之前调用 mount(Component, { global: { plugins: [store] } })
中用挂载选项安装插件,但 pinia 这边测试挂不挂载插件都是一样的,不会报错,测试也是正常运行,不知道这是不是 pinia 的特性,有知道的可以评论告知,但是在 pinia 文档中组件单元测试的案例是使用@pinia/testing
,它又是在挂载选项中安装了插件的,所以不知道我的操作是不是正确的// test-utils文档通过挂载选项安装插件
import { createStore } from 'vuex'
const store = createStore()
const wrapper = mount(Component, {
global: {
plugins: [store],
},
})
// pinia文档中的案例是
import { createTestingPinia } from '@pinia/testing'
const wrapper = mount(Counter, {
global: {
plugins: [createTestingPinia()],
},
})