如何结合Jest假定时器使用user-event测试库?
解决Jest假定时器与@testing-library/user-event v14.x交互超时问题
当启用Jest假定时器后,使用@testing-library/user-event模拟用户点击时出现测试超时、事件未触发的问题,核心原因是该库v14.x版本内部会通过setTimeout在模拟事件序列中添加延迟,而Jest假定时器会拦截这些异步操作,导致测试停滞。以下是几个无需修改依赖版本的可行解决方案:
临时切换定时器状态适配user-event
既然user-event需要真实定时器处理内部延迟逻辑,可以在执行user-event操作的前后,临时切换回真实定时器,操作完成后再切回假定时器:it(`fires onClick prop function when the button is clicked`, async () => { jest.useFakeTimers() let propFn = jest.fn() let app = RTL.render(<SampleComp onClick={propFn} />) // 临时启用真实定时器,让user-event内部延迟正常执行 jest.useRealTimers() await userEvent.click(app.queryByText('Test button')!) // 切回假定时器 jest.useFakeTimers() expect(propFn).toHaveBeenCalled() jest.useRealTimers() })配置user-event自定义定时器推进逻辑
user-event v14.x支持通过setup方法的advanceTimers选项,将内部的延迟逻辑绑定到Jest假定时器的推进方法上,这样无需切换真实定时器也能让事件序列正常执行:import userEvent from '@testing-library/user-event' it(`fires onClick prop function when the button is clicked`, async () => { jest.useFakeTimers() let propFn = jest.fn() let app = RTL.render(<SampleComp onClick={propFn} />) // 创建user实例时,指定用Jest的advanceTimersByTime处理内部延迟 const user = userEvent.setup({ advanceTimers: (delay) => jest.advanceTimersByTime(delay) }) await user.click(app.queryByText('Test button')!) expect(propFn).toHaveBeenCalled() jest.useRealTimers() })隔离假定时器的使用范围
如果当前测试本身不需要假定时器(比如示例中的点击测试),可以将假定时器的启用限制在真正依赖它的测试用例中,避免不必要的全局定时器拦截影响user-event的正常工作。比如用describe块对测试分组,只在需要的测试里启用假定时器。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

