mock对象通过side_effect直接赋异常类或实例可抛出指定异常,如valueerror或valueerror("msg");误用return_value或字符串会导致失败;支持列表顺序抛异常、patch装饰器中正确路径mock、side_effect设为函数时需用raise动态抛异常。

mock对象如何抛出指定异常
直接让side_effect指向一个异常类或实例,调用时就会原样抛出。这是最常用也最直观的方式。
常见错误是误用return_value——它只控制返回值,无法触发异常;或者把异常写成字符串(如"ValueError"),结果只是返回字符串而非抛出异常。
- 抛出异常类:
mock_obj.side_effect = ValueError(调用时抛ValueError()) - 抛出带参数的异常实例:
mock_obj.side_effect = ValueError("invalid input") - 按调用顺序抛不同异常:
mock_obj.side_effect = [1, ValueError, TypeError](第3次调用才抛ValueError)
patch装饰器中模拟异常的写法
用@patch修饰测试方法时,被mock的目标函数行为由传入的side_effect决定,不是靠return_value。
容易忽略的是:如果patch目标是模块内函数(比如requests.get),必须在测试所在模块的命名空间中patch,而不是在requests模块里patch——否则mock不生效。
- 正确写法(假设测试在
myapp.api中):@patch("myapp.api.requests.get") - 配合异常:
@patch("myapp.api.requests.get", side_effect=ConnectionError) - 若需复用,可在
setUp中用patch.start()并手动赋side_effect
验证异常是否被正确捕获和处理
仅让mock抛异常不够,还要确认被测代码确实按预期处理了它——比如有没有进except分支、是否返回默认值、日志是否记录等。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
别只断言assertRaises就结束;要检查副作用,比如状态变更、日志输出、返回值是否符合容错逻辑。
- 捕获异常本身:
with self.assertRaises(ValueError): func() - 检查日志:
self.assertLogs("myapp", level="ERROR")+assertIn("failed", logs.output[0]) - 验证返回值(容错路径):
self.assertEqual(func(), {"status": "fallback"})
side_effect设为函数时的异常抛出控制
当需要根据参数动态决定是否抛异常,或想在抛异常前做点事(如打日志、改状态),就把side_effect设为一个函数。
这个函数会被传入mock调用时的实际参数,返回值会被忽略,但若抛出异常,就会被原样向上冒泡——这点和直接赋异常实例效果一致,但更灵活。
- 示例:
mock_obj.side_effect = lambda x: 1 / x if x != 0 else ZeroDivisionError("x is zero")→ 错,应写成raise ZeroDivisionError("x is zero") - 正确写法:
mock_obj.side_effect = lambda x: (lambda: exec('raise ZeroDivisionError("x is zero")'))() if x == 0 else x * 2→ 更推荐拆成普通函数,可读性更好 - 实际建议:
def mock_behavior(x): if x
mock抛异常本身很简单,难的是确保异常路径的逻辑覆盖完整——比如网络超时、权限拒绝、数据解析失败这些不同异常是否都进了各自的处理分支,以及它们是否影响了外部状态。这些得靠检查副作用,不能只看异常有没有被抛出来。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










