Vue2 项目使用 Jest 单测单独通过、整文件运行失败如何解决?
问题根因
- 异步逻辑未等待完成就执行断言:组件
mounted钩子中调用的getAnalytics是异步方法,返回的Promise回调会进入微任务队列,执行shallowMount后直接读取property1时,回调还未执行,变量还未被赋值。单测试运行时事件循环压力小,可能刚好回调执行完成才跑断言,批量运行时执行时序混乱就会触发失败。 - Mock函数未被Jest托管:当前声明的
getAnalyticsmock是普通函数,不是Jest生成的mock实例,所以调用clearMocks、resetMocks等方法对它完全不生效,无法做到每个用例前重置mock状态。 - 模块缓存未正确清理:在测试文件顶部已经静态导入了
Analytics组件,jest.resetModules()只会清除后续导入的模块缓存,已经导入的组件不会重新加载,修改的mock也不会作用到已导入的组件上。
修复方案
步骤1:调整Mock声明,托管给Jest
将getAnalytics的mock改为Jest生成的mock函数,方便后续重置状态:
// analytics.spec.ts import { getAnalytics } from '@/client/analytics'; // 用jest.fn包裹mock实现 jest.mock('@/client/analytics', () => ({ getAnalytics: jest.fn(() => Promise.resolve(mockedData)), // 保持原有mockedData定义即可 }));
步骤2:在 beforeEach 中等待所有异步逻辑执行完成
可以安装flush-promises工具清空所有 pending 状态的Promise,再等待Vue更新完成:
// 顶部导入flush-promises,未安装的话先作为开发依赖安装即可 import flushPromises from 'flush-promises'; describe ('analytics.vue', () => { let wrapper; let comp; beforeEach(async () => { // 每次用例执行前清空mock调用记录 (getAnalytics as jest.Mock).mockClear(); const localVue = createLocalVue(); localVue.use(ElementUI); wrapper = shallowMount(Analytics, { localVue, mocks: { $route, // 保持原有$route mock即可 }, }); comp = wrapper.vm; // 等待所有异步Promise执行完成,再等待Vue视图更新 await flushPromises(); await wrapper.vm.$nextTick(); }); afterEach(() => { wrapper.destroy(); }); it('test 1', () => { expect(comp.$data.property1).toEqual('expectedValue'); }); it('test 2', () => { expect(comp.$data.property1).toEqual('expectedValue'); }); })
内容的提问来源于stack exchange,提问作者Amir Choubani
相关产品推荐
相关产品推荐

