likes
comments
collection
share

vitest 单元测试配合@vue/test-utils 之 pinia 篇

作者站长头像
站长
· 阅读数 26

what is vitest & VueTestUtils & pinia

vitest 是由 vite 提供支持的极速单元测试框架,VueTestUtils 是 Vue.js 的官方测试实用程序库,pinia 是 Vue.js 的状态管理库,以上均为各自官网对其的描述

demo

项目中使用状态管理是非常常见的,所以对它也可以来个单元测试,这里我们可能会有两个场景: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')
  })
})
  1. 第一个 demo 由三个部分组成,store、组件和测试文件
  2. store 里是一个常见的案例,使用了 SetupStore 的写法,与 OptionStore 相比,ref()就是state,computed()就是getters,function()就是actions,定义了一个 count,一个 count 自增的函数和计算属性双倍获取 count 值
  3. 组件的逻辑非常简单,点击按钮,增加 store 里的 count 值,页面显示实时数字
  4. 测试文件中因为是在单元测试环境下,所以需要在测试代码运行之前即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 是否与预期值一致

tips

虽然这仍是一个简单的 demo,但它还是有很多值得注意的知识点的

  • 测试环境:测试环境里是没有 pinia 的,所以我们需要在测试代码运行之前激活 pinia,所以用到了beforeEachsetActivePinia,这里使用beforeAll也可以,它是在所有测试代码运行之前调用
  • 在 test-utils 的文档里有 vuex 的测试案列,需要在 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()],
  },
})

其他文章

vitest 单元测试配合@vue/test-utils 之组件单元测试篇