返回

Vitest 实战:如何有效测试 Vue 3 中的 defineModel

vue.js

在 Vitest 中有效测试 Vue 3 中的 defineModel

什么是 defineModel?

defineModel 是 Vue 3 中引入的一种新响应式状态管理机制。它允许组件在不使用 Vuex 或其他状态管理库的情况下轻松管理其状态。

测试 defineModel

Vitest 中测试 defineModel 涉及以下步骤:

挂载组件和设置道具

使用 shallowMount 挂载组件并设置必要的道具。

更新组件状态

更新组件状态可以通过设置道具或直接更新 defineModel 来实现。

运行定时器

defineModel 经常使用定时器来管理状态变化。在 Vitest 中,使用 vi.runAllTimers() 运行所有挂起的定时器。

检查状态变化

检查组件状态是否按预期更改。可以使用比较组件状态或检查发出的事件来实现。

断言状态变化

最后,使用 expect 断言组件状态是否按预期更改。

测试示例

以下是一个测试 defineModel 的示例:

import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest'
import { shallowMount } from '@vue/test-utils'

import Toast from '../Toast.vue'

const props = {
  text: 'hello toast',
  time: 2500,
  modelValue: false
}

beforeEach(() => {
  vi.useFakeTimers()
})

afterEach(() => {
  vi.useRealTimers()
})

vi.useFakeTimers()

describe('Toast.vue', () => {
  it('Toast Props', async () => {
    const wrapper = shallowMount(Toast, {
      propsData: props
    })

    await wrapper.setProps({
      modelValue: true
    })

    vi.runAllTimers()

    await wrapper.vm.$nextTick()

    expect(wrapper.emitted()).toHaveProperty('update:modelValue')
    expect(wrapper.emitted('update:modelValue')).toHaveLength(1)
   
    // 使用 Object.is 检查对象相等
    expect(Object.is(wrapper.vm.modelValue, false)).toBe(true)
  })
})

常见问题解答

Q1. 如何测试 defineModel 中使用定时器的状态变化?
A1. 使用 vi.runAllTimers() 运行所有挂起的定时器。

Q2. 如何断言 defineModel 返回的对象是否按预期更改?
A2. 使用 Object.is 检查对象相等,因为它返回一个响应式对象。

Q3. 测试 defineModel 时需要考虑什么?
A3. 确保使用 beforeEach 挂钩设置模拟定时器,并在测试后使用 afterEach 挂钩重置它们。

Q4. 如何检查发出的事件以验证 defineModel 的行为?
A4. 使用 wrapper.emitted() 检查组件是否发出了预期的事件。

Q5. 是否需要设置定时器来测试 defineModel 的变化?
A5. 只有当 defineModel 使用定时器来管理状态变化时才需要设置定时器。