如何使用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
相关产品推荐
相关产品推荐

