You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js EventBus单元测试报错:期望$on调用1次实际为0如何解决

问题根因
  • 核心问题是组件与测试代码使用的EventBus不是同一个实例:组件中是直接import {EventBus} from 'eventbus'引入的独立导出实例,而你测试中mock的是挂载在Vue实例原型上的EventBus,二者完全无关,组件mounted阶段调用的$on根本没有落到你mock的jest函数上,自然调用次数为0。
  • 次要问题是测试代码中shallowMount创建wrapper的逻辑写在describe块外层、it用例之前,挂载时机早于mock初始化也可能导致执行异常。
修复方案
  1. 首先用jest直接mock你项目中eventbus模块的导出内容,替换整个模块的导出对象,保证组件引入的就是你mock的对象
  2. 调整测试代码结构,将wrapper创建放到用例执行前的钩子中,每次测试前重置mock调用记录,避免用例间干扰

修改后的测试代码参考:

// 第一步: mock整个eventbus模块,必须写在测试文件最顶部,import组件之前
jest.mock('eventbus', () => ({
  EventBus: {
    $on: jest.fn(),
    $off: jest.fn(),
    $emit: jest.fn()
  }
}))
// 引入要测试的组件和mock后的EventBus,此时组件内部引入的EventBus就是上面mock的对象
import MyComponent from './MyComponent.vue'
import { EventBus } from 'eventbus'

const $t = () => {}
let wrapper
describe('My component', () => { 
  // 每次用例执行前重新挂载组件,重置mock调用记录
  beforeEach(() => {
    jest.clearAllMocks()
    const params = { localVue, store, router,
      propsData: {
        isEdit: false
      },
      data(){
        return {
          loading: false,
          tabIndex: 1
        };
      },
      mocks:{
        $t
      },
    }
    wrapper = shallowMount(MyComponent, params)
  })

  it('Event bus', () => {
    // 直接引用mock的EventBus做断言即可
    expect(EventBus.$on).toHaveBeenCalledTimes(1);
    expect(EventBus.$on).toHaveBeenCalledWith('saveTerminal', expect.any(Function))
    // 如需验证事件触发后的执行逻辑,可以加如下断言(需提前给someOtherFunction挂载spy)
    // jest.spyOn(wrapper.vm, 'someOtherFunction')
    // EventBus.$emit('saveTerminal');
    // expect(wrapper.vm.someOtherFunction).toHaveBeenCalled()
  });
})

内容的提问来源于stack exchange,提问作者MariaZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:36:04