mock.patch路径必须匹配被测代码导入位置,如myapp/sdk_client.py中import requests则需patch"myapp.sdk_client.requests.get"而非"requests.get"。

mock.patch 路径必须匹配被测代码的导入位置
真实请求发出去了?八成是 patch 路径写错了。比如被测模块 myapp/sdk_client.py 里写了 import requests,然后调用 requests.get(url),那测试时就得打补丁到 myapp.sdk_client.requests.get,而不是 requests.get。
常见错误:@patch("requests.get") 看起来顺眼,但完全无效——因为被测代码压根没从全局 requests 模块拿函数,它用的是自己模块作用域里的 requests 引用。
- 先打开被测文件,看它是怎么 import 的:
import requests还是from requests import get还是from my_sdk import Client - 如果是前者,补丁目标是
"myapp.sdk_client.requests.get" - 如果是后者,目标是
"myapp.sdk_client.Client"或具体调用的方法,比如"myapp.sdk_client.client._send_request" - 路径中的点号对应模块层级,不能漏掉包名或文件名
requests_mock 比 unittest.mock 更省事,但只对 requests 有效
如果 SDK 底层走的是 requests(绝大多数 HTTP SDK 都是),直接上 requests_mock 是最快路径。它在 requests.Session.send 层打补丁,不碰 SDK 内部逻辑,还能按 URL、method、headers、JSON body 精确匹配。
安装:pip install requests-mock
立即学习“Python免费学习笔记(深入)”;
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 用装饰器:
@requests_mock.Mocker(),参数名必须叫mock或显式命名 - 拦截 GET:
mock.get("https://api.example.com/user/123", json={"id": 123}) - 拦截 POST 并校验 body:
mock.post("https://api.example.com/login", additional_matcher=lambda req: req.json()["username"] == "test") - 模拟超时:
mock.get(url, exc=requests.exceptions.Timeout) - 注意:如果 SDK 用的是
httpx或aiohttp,requests_mock完全无效,得换httpx.MockTransport或aioresponses
返回值要满足被测代码的实际访问方式
别直接 return_value={"status": "ok"} —— 大多数 SDK 会调用 response.json() 和读 response.status_code,而字典没有这些属性和方法。
正确做法分两种:
- 用
requests_mock:它返回的 mock response 天然支持.json()、.text、.status_code,不用额外构造 - 纯
unittest.mock场景:手动构造最小接口:mock_resp = Mock() mock_resp.status_code = 200 mock_resp.json.return_value = {"data": "ok"} mock_resp.text = '{"data": "ok"}' - 模拟错误响应时,只设
status_code = 404不够,还得确认被测逻辑真会检查它;若逻辑里写了response.raise_for_status(),就得用side_effect抛requests.exceptions.HTTPError
别只测“通路”,异常路径才是关键防线
一个只 mock 成功响应的测试,基本等于没测。真实世界里,网络超时、503、JSON 解析失败、重定向循环、空响应体……这些才是 SDK 容错能力的试金石。
- 超时:
mock_get.side_effect = requests.exceptions.Timeout - 连接拒绝:
mock_get.side_effect = requests.exceptions.ConnectionError - JSON 解析失败:
mock_resp.json.side_effect = ValueError("Invalid JSON") - 重定向太多:
mock_get.status_code = 302+ 手动控制重定向链(或用requests_mock的real_http=False配合多次注册) - 每个异常路径都要断言:SDK 是否抛了预期异常?是否返回了 fallback 值?日志是否记录?重试逻辑是否触发?
最容易被忽略的是「mock 对象没被真正调用」——加一句 mock_get.assert_called_once(),能立刻暴露 patch 失效或逻辑短路问题。

















