JS长任务拆分单元测试需验证拆分逻辑正确性、分片准确性、子任务独立执行及结果一致性;聚焦封装的调度函数,用假时间或mock替代真实API,覆盖空输入、单块、多块、聚合、错误传播等场景,并精确断言参数、顺序与结果。

JS 中长任务拆分的单元测试,核心是验证拆分逻辑是否正确、任务是否按预期分片、各片段能否独立执行且最终结果一致。不测浏览器 API(如 setTimeout 或 requestIdleCallback)本身,而是聚焦你封装的拆分调度逻辑。
明确被测函数职责
先确认你要测的是哪个函数——通常是类似 splitAndRun(task, chunkSize) 或 scheduledRun(items, handler, options) 这样的工具函数。它应具备:
- 接收原始数据或任务列表
- 按指定粒度(如每 10 项、每 5ms 预估耗时)切分成多个子任务
- 安排子任务异步执行(用
queueMicrotask、setTimeout(0)或模拟的“空闲时机”) - 返回 Promise,resolve 最终聚合结果(可选)
用假时间/可控调度代替真实异步
避免测试中依赖真实定时器导致不稳定或变慢。推荐方式:
- 用
jest.useFakeTimers()(Jest)冻结时间,再手动advanceBy触发回调 - 把调度函数(如
scheduleNextChunk)作为参数注入,测试时传入同步执行的 mock 函数 - 对基于
requestIdleCallback的逻辑,直接 mock 全局函数并立即调用 callback
例如:
jest.mock('requestIdleCallback', (cb) => cb({ timeRemaining: () => 10 }));
覆盖关键测试场景
每个测试用例聚焦一个行为点:
- 空输入:传入空数组,检查是否快速 resolve,不抛错、不调度子任务
- 单块即完成:数据量 ≤ chunkSize,应只执行一次 handler,不触发多次调度
- 多块拆分:输入 25 项、chunkSize=10 → 应调度 3 次(10+10+5),且每次传入对应子数组
- 结果聚合正确:handler 对每项返回值,最终 Promise resolve 的数组顺序与原始一致、内容无遗漏
- 错误传播:某次子任务 reject,整体 Promise 应 reject,且不继续后续块(除非配置了容错)
断言要具体,避免只验“有没有跑”
别只写 expect(mockHandler).toHaveBeenCalledTimes(3),还要验证:
- 每次调用的参数是否为正确的子数组(
expect(mockHandler).toHaveBeenNthCalledWith(1, [a,b,c])) - 执行顺序是否符合预期(尤其涉及状态累积时)
- 返回 Promise 的 resolved 值是否结构匹配(可用
toEqual深比) - 若支持中断(如 cancel token),验证取消后不再执行后续块


















