单元测试中应通过 mock 替代真实 HTTP 请求,优先 mock 业务直接调用的客户端(如 axios.get),避免底层补丁;采用依赖注入和接口契约提升可测性与类型安全;断言聚焦业务结果而非调用路径。

在单元测试中彻底解耦外部网络环境,核心是**不让测试代码真正发出 HTTP 请求**,而是用可控的模拟(mock)替代真实网络调用。这不是“绕过”问题,而是通过设计让依赖可替换、行为可预测。
用测试框架的 mock 功能拦截请求
现代测试工具(如 Jest、Vitest)能直接 mock 模块或全局 API,无需修改源码:
- 对 fetch 或 axios 等客户端做顶层 mock:Jest 提供
jest.mock('axios')或global.fetch = jest.fn(),然后手动定义返回值和状态码 - 对具体业务函数做行为级 mock:比如一个
getUser(id)函数内部调用了fetch,你可以在测试里 mock 它的整个实现,只关心输入输出是否符合预期 - 利用
beforeEach和afterEach清理 mock 状态,避免测试间污染
把网络请求抽象成可注入的依赖
不推荐在业务逻辑里直接写 fetch(url)。更合理的方式是将请求能力作为参数传入,或通过工厂函数提供:
- 函数式注入:把请求函数作为参数,测试时传入返回固定数据的模拟函数
- 类构造器注入:服务类接收一个
httpClient实例,测试时传入带 mock 方法的 fake client - 配合接口契约(如 TypeScript 的
HttpClient类型),让替换更安全、类型更清晰
避免直接依赖全局对象或第三方库内部细节
不要 mock XMLHttpRequest.prototype.open 这类底层 API,容易出错且难维护:
立即学习“Java免费学习笔记(深入)”;
- 优先 mock 你实际调用的那层——比如你用的是
axios.get,就 mockaxios.get,而不是它的内部实现 - 避免在测试中依赖未导出的私有方法或模块路径,否则重构时测试会大面积失败
- 如果必须拦截底层(如调试场景),用
Proxy包装目标对象比猴子补丁更安全,但日常单元测试中不推荐
验证行为,而非实现路径
测试重点应放在“结果是否正确”,而不是“它有没有调用 fetch”:
- 断言返回的数据结构、错误类型、状态码等业务结果
- 用
jest.spyOn或vi.spyOn验证调用次数和参数,仅用于辅助确认流程,不是主断言依据 - 对异常路径(如网络超时、404、500)单独覆盖,确保错误处理逻辑健壮


















