Vue.js EventBus单元测试报错:期望$on调用1次实际为0如何解决
问题根因
- 核心问题是组件与测试代码使用的
EventBus不是同一个实例:组件中是直接import {EventBus} from 'eventbus'引入的独立导出实例,而你测试中mock的是挂载在Vue实例原型上的EventBus,二者完全无关,组件mounted阶段调用的$on根本没有落到你mock的jest函数上,自然调用次数为0。 - 次要问题是测试代码中
shallowMount创建wrapper的逻辑写在describe块外层、it用例之前,挂载时机早于mock初始化也可能导致执行异常。
修复方案
- 首先用jest直接mock你项目中
eventbus模块的导出内容,替换整个模块的导出对象,保证组件引入的就是你mock的对象 - 调整测试代码结构,将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
相关产品推荐
相关产品推荐

