vue3组件单元测试核心是验证props输入与emit输出,vitest因轻量快启及与vite集成成为首选;需配置happy-dom环境,通过mount传props并断言dom/状态响应,用emitted()校验事件名、次数及参数,注意异步更新需等待。

组件单元测试的核心是验证它在给定输入(props)下是否产生预期输出(emitted 事件、DOM 渲染、内部状态),尤其对 Vue3 组件,Props 和 Emit 是父子通信的主干,必须重点校验。Vitest 因其轻量、快启动、与 Vite 深度集成,已成为 Vue3 项目首选测试工具。
准备 Vitest 环境
确保项目已使用 Vite 构建。安装 Vitest 并配置基础环境:
- 运行 pnpm add -D vitest @vue/test-utils(或 npm/yarn 对应命令)
- 在 vite.config.ts 中添加 test 配置,指定环境为 happy-dom(比 jsdom 更快,适合 Vue 组件 DOM 测试)
- 创建 vitest.config.ts 或直接在 vite.config.ts 中写:
test: { environment: 'happy-dom', globals: true } - 在 package.json 添加脚本:"test": "vitest"
测试 Props 的接收与响应逻辑
Props 不只是静态传入,关键看组件是否根据 props 正确渲染、计算或触发行为。例如一个按钮组件接收 disabled prop:
- 用 mount(Comp, { props: { disabled: true } }) 挂载并传入 props
- 通过 wrapper.find('button').attributes('disabled') 断言属性是否存在
- 若 props 影响内部 ref 或计算属性,可访问 wrapper.vm.xxx 直接读取实例状态
- 避免只测“有没有传”,要测“传了之后组件是否按逻辑反应”——比如 disabled 为 true 时点击不触发事件、样式类是否添加
断言 Emit 的事件名称与参数
Emit 是组件向外暴露行为的唯一契约,必须精确校验事件名、触发时机和携带参数。核心方法是 wrapper.emitted():
- wrapper.emitted('submit') 返回一个数组,每个元素是该事件一次触发时的参数列表(即使只传一个值,也是 [value])
- 先触发交互:如 wrapper.find('form').trigger('submit')
- 再检查:expect(wrapper.emitted('submit')).toHaveLength(1)
- 校验参数:expect(wrapper.emitted('submit')![0]).toEqual([{ name: 'Alice', age: 25 }])
- 若 emit 多次,emitted('event') 数组长度即为次数,索引对应第几次触发
组合测试:Props 变化 → 触发 Emit
真实场景中,Props 改变可能影响 emit 行为。例如一个开关组件接收 modelValue,点击后 emit update:modelValue:
- 挂载时传入初始值:mount(Switch, { props: { modelValue: false } })
- 模拟点击:wrapper.find('input').trigger('click')
- 断言 emit:expect(wrapper.emitted('update:modelValue')![0]).toEqual([true])
- 还可进一步测试:当 props 为 true 时点击,是否 emit false;是否支持 .sync 语法糖等边界情况
不复杂但容易忽略:每次 mount 后 wrapper 是全新实例,emitted() 只记录本次挂载生命周期内的事件;异步 emit 需配合 await nextTick() 或 waitFor 等待更新完成再断言。










