如何使用@testing-library/vue测试带debounce防抖的Vue组件emit事件
问题根因
测试失败的核心原因是添加的300ms防抖逻辑会延迟update回调的执行时机,测试代码在输入完成后立刻执行断言时,防抖回调还未触发,因此emitted()中没有对应的update-items事件。
解决方案
以下三种方案均可解决该问题,按推荐优先级排序:
方案1:使用假定时器(推荐,测试执行速度快)
通过测试框架内置的假定时器模拟时间流逝,不需要真实等待300ms,不会延长测试整体执行时间:
import { fireEvent } from '@testing-library/vue' // 可选,解决userEvent和假定时器冲突问题 it('should emit [update-items] event if the query length typed on search input field is equal or greater than three', async () => { // 启用假定时器,Jest环境用jest,Vitest环境替换为vi jest.useFakeTimers() const { container, emitted } = await render(template); const el = container.querySelector('input'); // 如果userEvent.type和假定时器出现冲突,替换为下面两行手动触发输入 // el.value = 'abcd' // await fireEvent.input(el) await userEvent.type(el, 'abcd'); // 快进时间执行所有待执行的定时器任务 jest.runAllTimers() // 等待所有微任务执行完成 await Promise.resolve() expect(emitted()).toHaveProperty('update-items'); // 重置为真实定时器,避免影响其他测试用例 jest.useRealTimers() });
方案2:调用lodash防抖函数的flush方法主动执行
lodash的debounce返回的函数自带flush方法,可以主动触发待执行的防抖回调,不需要调整定时器:
it('should emit [update-items] event if the query length typed on search input field is equal or greater than three', async () => { // 从render返回值中拿到组件实例 const { container, emitted, component } = await render(template); const el = container.querySelector('input'); await userEvent.type(el, 'abcd'); // 主动执行防抖回调 component.update.flush() expect(emitted()).toHaveProperty('update-items'); });
方案3:真实等待防抖延迟结束(不推荐)
直接等待超过防抖时长的时间即可,实现简单但会增加测试执行时间:
it('should emit [update-items] event if the query length typed on search input field is equal or greater than three', async () => { const { container, emitted } = await render(template); const el = container.querySelector('input'); await userEvent.type(el, 'abcd'); // 等待350ms,保证防抖回调执行完成 await new Promise(resolve => setTimeout(resolve, 350)) expect(emitted()).toHaveProperty('update-items'); });
内容的提问来源于stack exchange,提问作者Vinicius Cainelli
相关产品推荐
相关产品推荐

