side_effect需传异常实例(如ConnectionError("timeout"))或可调用对象才能触发异常;传异常类会报TypeError;常见错误包括误设return_value、patch范围错误或参数顺序错位。

mock的side_effect怎么触发异常而不是返回值
直接赋值 side_effect 为一个异常类(比如 ConnectionError)不会抛出实例,而是抛出类本身——这会导致 TypeError: exceptions must derive from BaseException。必须传入异常实例,或可调用对象。
实操建议:
- 传异常实例:
side_effect=ConnectionError("timeout") - 传元组列表实现多次调用不同行为:
side_effect=[ValueError("bad url"), {"status": 200, "data": "ok"}](第一次抛异常,第二次正常返回) - 传函数时注意签名要匹配被 mock 函数的参数,否则调用会失败
requests.get被mock后,为什么response.json()还报错
只 mock requests.get 并让它抛异常,能覆盖网络层失败;但如果测试代码里仍尝试调用 response.json(),说明 mock 返回了 Response 对象而非异常——即 side_effect 没生效,或被错误地赋给了 return_value。
常见错误现象:
- 误写成
mock_get.return_value = ConnectionError("timeout")(这是把异常当返回值,不会抛出) - 忘记 patch 范围,比如在测试模块里 patch
"requests.get",但被测函数实际导入的是from requests import get,此时应 patch"mymodule.get" - 使用
@patch但参数顺序错位,导致 mock 对象没注入到测试函数中
如何让side_effect按真实网络异常逻辑分层抛出
真实请求可能在不同阶段失败:DNS 解析、TCP 连接、TLS 握手、HTTP 状态码非 2xx。单元测试不必复刻全部,但需区分语义——比如 ConnectionError 表示连不上服务,Timeout 表示响应慢,HTTPError 表示服务返回了 500/404。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
推荐做法:
- 用
side_effect分别模拟:ConnectionError、requests.Timeout、requests.HTTPError(response=Mock(status_code=503)) - 避免全用
Exception,否则断言难写,也掩盖了错误分类意图 - 如果被测函数有重试逻辑,可用列表形式让前几次抛
Timeout,最后一次返回成功响应
unittest.mock.patch 的作用域和清理容易被忽略的点
patch 不是“一劳永逸”,它只在作用域内生效。手动 start/stop 容易漏掉 stop,用上下文管理器最安全。
实操建议:
- 优先用
with patch("requests.get") as mock_get:,退出 with 块自动还原 - 装饰器方式要注意类方法测试中
self参数位置,mock 对象总在第一个参数之后 - 多个 patch 嵋嵌套顺序:越靠近函数体的 patch 越先执行,也越先被清理——顺序反了可能导致 mock 错位
复杂点在于,如果测试中用了 patch.multiple 或嵌套 patch,且其中某个 mock 在异常路径中未被正确清理,后续测试可能意外继承前一次的 side_effect 设置。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










