Vue 3 单文件组件单元测试核心是 Vitest + @vue/test-utils,覆盖 props、事件、条件渲染等关键路径;需配置 happy-dom 环境、合理用例设计及覆盖率分析。

Vue 3 单文件组件的单元测试,核心是用 Vitest 运行测试、用 @vue/test-utils 挂载和交互组件,再配合覆盖率工具补全验证逻辑。不追求用例数量,而重在覆盖关键路径:props 输入、用户操作、事件输出、条件渲染、错误边界。
安装与基础配置
确保项目基于 Vite(推荐),执行以下命令:
- 安装依赖:
npm install -D vitest @vue/test-utils@next happy-dom - 在
vite.config.ts中添加测试配置(需顶部加三斜线引用):/// <reference types="vitest" />
然后在defineConfig的test字段中设置:environment: 'happy-dom'(模拟 DOM 环境)include: ['src/components/**/*.{test,spec}.ts'] - package.json 中加入脚本:
"test": "vitest"和"coverage": "vitest run --coverage"
写一个典型组件测试
以带计算属性和按钮交互的组件为例(如 Hello.vue):
- 用
mount挂载,传入 props:const wrapper = mount(Hello, { props: { count: 5 } }) - 查 DOM 元素:
wrapper.find('button')或wrapper.text() - 触发事件并等待响应:
await wrapper.find('button').trigger('click') - 断言结果:
expect(wrapper.text()).toContain('5 x 3 = 15'),或检查 emitted:expect(wrapper.emitted()).toHaveProperty('submit')
提升覆盖率的关键点
80%+ 覆盖率不是靠堆用例,而是结构化补全分支与边界:
立即学习“前端免费学习笔记(深入)”;
- 每个布尔 prop 至少测
true和false两种状态(如disabled) - 显式覆盖
v-if/v-else分支:先让条件为真,断言元素存在;再设为假,断言元素消失 - 测试 slot 默认内容:
slots: { default: () => 'fallback text' } - 模拟异常路径:mock 接口失败、传非法 props、触发 emit 抛错,验证错误提示是否渲染
- 对
defineModel场景,测试双向绑定是否同步更新父级值
查看与解读覆盖率报告
运行 npm run coverage 后,打开 coverage/lcov-report/index.html:
-
%stmts(语句覆盖率):每行可执行代码是否都走到了 -
%branches(分支覆盖率):if/else、三元、v-if等所有分支是否都被执行 - 低覆盖常见位置:watch 回调未触发、onMounted 中异步逻辑未 await、provide/inject 未 mock、slot fallback 未测


















