Vue 2 单元测试中模拟事件的核心是 trigger 触发交互并用 emitted() 断言 $emit:trigger 模拟 click/input 等事件(需 await 等待异步更新),emitted() 检查事件是否发出、次数及参数,注意避免直接调用方法或依赖内部状态。

在 Vue 2 的单元测试中,用 Vue Test Utils 模拟组件事件触发,核心是两步:一是通过 trigger 方法模拟用户交互(如 click、input),二是用 emitted() 断言组件是否按预期调用了 $emit。
用 trigger 模拟点击、输入等行为
Vue Test Utils 的 trigger 方法可模拟 DOM 事件,触发组件内部的事件监听器。它会同步执行事件回调,但注意:若回调中修改响应式数据或触发异步操作,DOM 更新是异步的,需配合 await 等待更新完成。
- 点击按钮:
await wrapper.find('button').trigger('click') - 输入文本:
await wrapper.find('input').setValue('hello')(setValue内部已封装trigger('input')) - 提交表单:
await wrapper.find('form').trigger('submit') - 支持自定义事件类型,如
trigger('custom-event'),但前提是组件模板中已绑定对应监听器(如@custom-event)
用 emitted() 验证 $emit 是否发生
emitted() 返回一个对象,记录组件实例所有被触发的自定义事件及其参数。它不依赖 DOM,只捕获 this.$emit 调用。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 检查事件是否发出:
expect(wrapper.emitted()).toHaveProperty('submit') - 检查事件次数:
expect(wrapper.emitted('increment')).toHaveLength(2) - 检查事件参数:
expect(wrapper.emitted('submit')[0]).toEqual(['user@example.com'])(第一次触发的参数数组) - 若事件未触发,
emitted('xxx')返回undefined,建议先用toBeDefined做存在性断言
处理异步更新和事件时序
Vue 2 的响应式更新是异步的,尤其涉及 v-model、nextTick 或 watch 时。直接在 trigger 后断言 DOM 或 emitted 可能失败。
立即学习“前端免费学习笔记(深入)”;
- 推荐统一使用
await:await wrapper.find('button').trigger('click')—— Vue Test Utils 的trigger和setValue已返回 Promise,等待 Vue 完成更新 - 若组件内有
this.$nextTick或setTimeout,需确保 Jest 的定时器已启用(jest.useFakeTimers())或显式await wrapper.vm.$nextTick() - 避免在多个
trigger之间漏掉await,否则可能断言到中间状态
常见误区与建议
有些写法看似合理,实则偏离测试本质,容易导致脆弱测试。
- 不要直接调用组件方法(如
wrapper.vm.handleClick())—— 这是在测实现,不是测行为 - 不要依赖内部 data 或 computed 的具体值做断言,除非该值直接影响输出(如
error计算属性控制 DOM 显示) - 优先用语义化选择器,比如
data-testid="submit-btn",而非.btn-primary,避免样式变更导致测试失败 - 每个测试应独立准备状态,避免
beforeAll共享wrapper实例;推荐用beforeEach重建干净实例

















