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

如何使用Vue Test Utils测试全局Event Bus?

如何测试Vue全局Event Bus的事件触发与监听?

首先,咱们先搞清楚你遇到的核心问题:你在测试代码里是先触发了input事件(此时组件已经通过Event Bus发出了coupon-applied事件),之后才绑定的事件监听,所以自然监听不到已经发生的事件。这就像你错过了一场直播,事后再打开直播链接,当然看不到之前的内容啦。

下面给你两种实用的解决方案,结合你的代码来修改:

方案一:提前绑定Event Bus监听,用异步断言捕获事件

我们需要在触发组件的input事件之前,就绑定好Event Bus的监听,并且用测试框架的异步回调(比如done)来确认事件确实被触发了。修改你的测试代码如下:

import expect from 'expect';
import { mount } from '@vue/test-utils';
import CouponCode from '../src/components/CouponCode.vue';
import { EvtBus } from '../src/EvtBus.js';

describe('Reminders', () => {
  let wrp;
  beforeEach(() => {
    wrp = mount(CouponCode);
  });

  it('broadcasts the percentage discount when a valid coupon code is applied', (done) => {
    // 第一步:先绑定Event Bus的监听,放在触发事件之前!
    EvtBus.$on('coupon-applied', () => {
      console.log('coupon was applied through event bus');
      // 这里可以添加具体的断言,比如确认事件触发逻辑正确
      expect(true).toBe(true);
      done(); // 告诉测试框架异步操作完成,避免测试超时
    });

    // 第二步:触发组件的input事件
    let code = wrp.find('input.coupon-code');
    code.element.value = '50OFF';
    code.trigger('input');

    // 保留原有的组件实例事件断言
    expect(wrp.emitted('applied')).toBeTruthy();
  });
});

方案二:用模拟函数跟踪Event Bus的$emit调用

如果你不想用异步回调,也可以通过模拟EvtBus.$emit方法,直接断言它是否被调用以及调用参数是否正确。这种方法更简洁,也更适合同步场景:

如果你用Jest(带Spy功能):

import expect from 'expect';
import { mount } from '@vue/test-utils';
import CouponCode from '../src/components/CouponCode.vue';
import { EvtBus } from '../src/EvtBus.js';

describe('Reminders', () => {
  let wrp;
  beforeEach(() => {
    wrp = mount(CouponCode);
    // 在每个测试前,给$emit方法添加Spy
    jest.spyOn(EvtBus, '$emit');
  });

  // 测试后恢复原始$emit,避免影响其他测试
  afterEach(() => {
    EvtBus.$emit.mockRestore();
  });

  it('broadcasts the percentage discount when a valid coupon code is applied', () => {
    let code = wrp.find('input.coupon-code');
    code.element.value = '50OFF';
    code.trigger('input');

    expect(wrp.emitted('applied')).toBeTruthy();
    // 直接断言Event Bus的$emit被调用,且参数是'coupon-applied'
    expect(EvtBus.$emit).toHaveBeenCalledWith('coupon-applied');
  });
});

如果你用Mocha/Expect(手动模拟):

如果没有Jest的Spy功能,咱们可以手动替换$emit为一个自定义函数来跟踪调用:

import expect from 'expect';
import { mount } from '@vue/test-utils';
import CouponCode from '../src/components/CouponCode.vue';
import { EvtBus } from '../src/EvtBus.js';

describe('Reminders', () => {
  let wrp;
  let originalEmit;
  beforeEach(() => {
    wrp = mount(CouponCode);
    // 保存原始的$emit方法
    originalEmit = EvtBus.$emit;
  });

  afterEach(() => {
    // 恢复原始$emit,避免污染其他测试
    EvtBus.$emit = originalEmit;
  });

  it('broadcasts the percentage discount when a valid coupon code is applied', () => {
    let emitCalled = false;
    // 替换$emit为自定义函数,跟踪是否触发了目标事件
    EvtBus.$emit = (...args) => {
      if (args[0] === 'coupon-applied') {
        emitCalled = true;
      }
      // 可选:保留原始的$emit行为
      originalEmit(...args);
    };

    let code = wrp.find('input.coupon-code');
    code.element.value = '50OFF';
    code.trigger('input');

    expect(wrp.emitted('applied')).toBeTruthy();
    expect(emitCalled).toBe(true);
  });
});

额外:测试组件是否监听了Event Bus事件

如果还要测试组件在created钩子中是否正确绑定了coupon-applied的监听,可以通过Spy EvtBus.$on方法来验证:

it('registers a listener for the coupon-applied event on mount', () => {
  const onSpy = jest.spyOn(EvtBus, '$on');
  mount(CouponCode); // 挂载组件,触发created钩子
  // 断言$on被调用,且参数是目标事件名和一个函数
  expect(onSpy).toHaveBeenCalledWith('coupon-applied', expect.any(Function));
  onSpy.mockRestore();
});

总结一下:

  • 测试Event Bus的事件触发:要么提前绑定监听并使用异步断言,要么用模拟函数跟踪$emit的调用
  • 测试Event Bus的事件监听:可以通过Spy $on方法,或者触发Event Bus事件后断言组件的行为变化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:48:00