关键在于可控、可观察、可断言:用msw或fetch mock隔离后端,分层定义成功/失败响应;拆解为小函数并导出,async/await逐层测试+断言;并发用promise.allsettled验证错误收集;加时间戳日志定位问题。

测试多次异步嵌套的网络请求逻辑,关键不是“跑通”,而是**可控、可观察、可断言**。直接在浏览器里点按钮或靠手动 Postman 调用,既难覆盖分支(比如某次请求失败),也难验证执行顺序和数据流转。下面从实操角度给出几种可靠方法。
用 Mock 服务隔离后端依赖
真实接口不稳定、响应慢、数据不可控,会干扰测试本身。推荐用 Mock Service Worker(MSW) 或 jest.mock + fetch mock 拦截请求,返回预设响应。
- 对嵌套链中每一层接口(如 A → B → C),单独定义 mock 响应,包括成功、空数组、报错等边界情况
- 例如:让接口 A 返回
{"data": ["dept1", "dept2"]},再让接口 B 对combatUnit="dept1"返回正常数据,对"dept2"返回{"data": {"list": null}},从而验证你识别异常部门的逻辑 - 这样就能在单元测试里稳定复现“B 接口某次调用 data.list 为 null”的场景,无需等待真实后端
用 async/await + try/catch 分段验证流程
把嵌套逻辑拆成小函数,每个函数负责一次请求及后续处理,并导出供测试调用。测试时用 await 逐层执行,用 expect 断言中间结果。
- 不要写
fetch(A).then(res => fetch(B)).then(...)这类匿名链式调用——它难以打桩、无法单步断言 - 改写为:
async function fetchDepartments() { /* 请求 A */ } async function fetchAreaData(combatUnit) { /* 请求 B */ } async function runFullFlow() { const depts = await fetchDepartments(); const results = []; for (const dept of depts) { const res = await fetchAreaData(dept); if (!res.data?.list) console.warn(`部门 ${dept} 数据为空`); results.push(res); } return results; } - 测试时可分别 mock
fetchDepartments返回指定数组,再 mockfetchAreaData按入参返回不同结构,最后检查 warn 输出或 results 内容
用 Promise.all 或 Promise.allSettled 测试并发行为
如果嵌套实际是“先取部门列表,再并行调用多个 B 接口”,那测试重点就变成:是否正确发起所有请求?是否统一处理失败?
- 用
Promise.allSettled替代Promise.all,确保即使某个 B 请求失败,也能拿到全部结果状态(fulfilled/rejected) - 测试时 mock 多个 B 请求,故意让其中一两个 reject,验证你的错误收集逻辑(比如汇总哪些部门调用失败)是否生效
- 注意:避免在测试中用
setTimeout模拟延迟——它不可靠;改用 MSW 的delay配置,或 jest 的advanceTimersByTime
加日志与时间戳辅助调试
嵌套深时,光看 console 很难理清执行流。在关键节点打印带时间戳的标记:
- 在请求 A 开始前打
console.time("full-flow"),结束后console.timeEnd - 每发起一个 B 请求,打印
`[B-${combatUnit}] start at ${Date.now()}`;收到响应后打`[B-${combatUnit}] done, took X ms` - 配合浏览器 DevTools 的 Network 面板或 VS Code 的 Debug Console,能快速定位哪一层卡住、哪一次超时











