直接用 patch 比 pytest-mock 的 mocker 更可控,因其避免自动作用域管理导致的嵌套 patch 失效、多层引用 mock 不生效等问题;mocker.patch 更简洁且自动清理,链式调用支持多 mock,但混用手动 patch 易引发 cleanup 错乱。

为什么直接用 patch 比 pytest-mock 的 mocker 更可控
因为 pytest-mock 提供的 mocker fixture 本质是封装了 unittest.mock.patch,但自动管理作用域和清理——这在多数场景下省事,可一旦涉及嵌套 patch、多层模块引用或需要提前 stop/reset mock,反而容易失控。比如你 mock 了 requests.get,但被测函数内部又调用了另一个封装了 requests 的工具类,结果 mock 没生效,报 ConnectionError。
- 优先用
mocker.patch('requests.get'),它比手动 importpatch更简洁,且自动 teardown - 若需多个 mock(如同时 mock
requests.get和json.loads),用mocker.patch链式调用,别堆叠装饰器 - 避免在测试函数参数里混用
mocker和手动patch,容易触发 cleanup 顺序错乱
如何让 mock 返回不同 HTTP 状态码和 JSON 数据
外部 API 不总成功,测试必须覆盖 404、500、超时等情形。直接 return 一个 Mock 对象不够,得构造带 status_code、json() 方法和 raise_for_status() 行为的响应对象。
- 用
mocker.Mock()手动构造响应:mock_resp = mocker.Mock(status_code=404, json=lambda: {'error': 'not found'}) - 对
raise_for_status,设 side_effect:mock_resp.raise_for_status.side_effect = requests.HTTPError('404 Client Error') - 若要模拟超时,让
side_effect抛出requests.Timeout,别 mocktime.sleep - 注意:不要 mock
requests.Session.request后再调get,应直接 mockrequests.get或对应方法名
什么时候不该用 pytest-mock,而该上 responses 库
当你的测试开始反复构造响应对象、还要校验请求 URL/headers/query 参数是否匹配时,pytest-mock 就显得笨重了。它不验证真实 HTTP 请求结构,只管“有没有调用”,容易漏掉拼写错误的 endpoint 或少传 header。
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
-
responses能注册真实 HTTP 请求规则,比如:responses.add(responses.GET, 'https://api.example.com/users', json={'id': 1}, status=200) - 它会拦截所有
requests发出的请求,自动匹配 method + url,不匹配就抛异常,逼你写准 - 适合集成测试前的快速验证,或需要复用同一组 mock response 的多个测试函数
- 缺点:不能 mock 非
requests的 HTTP 客户端(如httpx),得换库或退回到patch
mock 外部调用后,怎么验证是否真发了请求、传了什么参数
光让 mock 返回值还不够,得确认代码确实按预期调用了 API——比如是否用了正确的 token、是否带了 Content-Type: application/json、是否重试了三次。
立即学习“Python免费学习笔记(深入)”;
- 用
assert mock_get.called判断是否调用;assert mock_get.call_count == 1看次数 - 查参数:
mock_get.assert_called_with('https://api.example.com/data', headers={'Authorization': 'Bearer xyz'}) - 若参数复杂(如含动态 timestamp),用
mock_get.call_args拆解:args, kwargs = mock_get.call_args; assert kwargs['timeout'] == (3, 10) - 注意:如果被测函数里用了
**kwargs透传,mock 的call_args可能藏在字典里,得 print 出来看结构
mock 外部依赖不是为了跳过逻辑,而是把不可控的部分锁死——但锁得太松(比如没校验参数)或太死(比如 hardcode 了本该由配置驱动的 URL),都会让测试失去意义。

















