Jest单元测试中如何调用requestAnimationFrame的实际回调函数
触发mock的requestAnimationFrame回调的测试方法
核心逻辑
当你将window.requestAnimationFrame mock为jest.fn()后,mock实例会自动存储所有调用时传入的参数,也就是你传入的回调函数。你只需要手动提取该回调并执行,就能触发回调内部的所有逻辑,完成断言。
具体操作步骤
场景1:手动初始化纯jest.fn() mock
即你主动写了window.requestAnimationFrame = jest.fn()的情况:
- 触发业务逻辑执行,让代码走到调用
requestAnimationFrame的分支 - 从mock的调用记录中提取回调:
const rafCallback = window.requestAnimationFrame.mock.calls[0][0]mock.calls是所有raf调用的参数集合,每一项对应一次调用的入参数组,因为raf只有1个参数(回调),所以取第0个元素即可
- 直接执行回调:
rafCallback() - 此时即可正常断言回调内部的
process、clearTimeout等逻辑的执行情况
场景2:使用Jest fake timers 统一模拟异步定时器
如果你已经调用过jest.useFakeTimers(),Jest会自动接管包括requestAnimationFrame在内的所有定时器/动画API,无需手动提取回调:
- 触发业务逻辑执行后,直接调用
jest.runAllTimers(),会自动执行所有待运行的raf、setTimeout、setInterval回调 - 也可通过
jest.advanceTimersByTime(16)模拟16ms(单帧标准时长)的时间流逝,精准触发单帧对应的raf回调
完整测试用例示例
// 先mock业务依赖 const mockProcess = jest.fn(); window.clearTimeout = jest.fn(); // 引入业务逻辑(需在依赖mock完成后引入) import { yourBusinessLogicFn } from './your-code-path'; describe('raf回调逻辑测试', () => { beforeEach(() => { jest.clearAllMocks(); // 初始化raf mock window.requestAnimationFrame = jest.fn(); // 执行业务逻辑,触发raf调用 yourBusinessLogicFn(); }); test('raf回调执行时触发对应业务逻辑', () => { // 断言raf被正确调用 expect(window.requestAnimationFrame).toHaveBeenCalledTimes(1); // 提取并执行回调 const rafCallback = window.requestAnimationFrame.mock.calls[0][0]; rafCallback(); // 断言内部逻辑执行 expect(mockProcess).toHaveBeenCalledWith('postProcess'); expect(window.clearTimeout).toHaveBeenCalled(); }); });
注意事项
- 如果业务逻辑中多次调用
requestAnimationFrame,可通过mock.calls的不同下标对应提取不同调用的回调,比如第二次调用的回调为window.requestAnimationFrame.mock.calls[1][0] - 执行回调前注意重置其他mock的调用记录,避免上一个测试用例的调用记录干扰断言结果
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

