如何用pytest raises同时验证异常处理逻辑及日志输出
解决方法
问题出在测试里没mock my_operation函数,导致调用真实的my_operation时,异常直接中断了流程,没触发my_function里的异常处理逻辑。下面是具体的解决步骤:
1. 修正原代码的方法定义(可选但符合规范)
原MyClass.my_function用了cls当参数,却没加@classmethod装饰器,实例调用时会把实例对象传给cls,虽然不影响异常处理,但不符合Python编码规范,建议调整:
from some_other_module import my_operation import logging class MyClass: def my_function(self): # 实例方法用self try: my_operation() except Exception as exc: logging.info("something went wrong") raise # 如果是类方法,需添加装饰器: # @classmethod # def my_function(cls): # try: # my_operation() # except Exception as exc: # logging.info("something went wrong") # raise
2. 编写正确的pytest测试用例
用unittest.mock.patch来mockmy_operation,让它抛出可控异常;再用pytest自带的caplog捕获日志,同时验证异常是否被重新抛出:
import pytest import logging from unittest.mock import patch from your_module import MyClass # 替换为原代码所在的模块名 def test_my_function(caplog): # 设置日志捕获级别为INFO,确保能抓到目标日志 caplog.set_level(logging.INFO) # mock my_operation,让它抛出指定异常 with patch('your_module.my_operation') as mock_op: mock_op.side_effect = Exception("测试用异常") obj = MyClass() # 验证异常被重新抛出 with pytest.raises(Exception): obj.my_function() # 检查日志是否正确输出 assert "something went wrong" in caplog.text # 可选:确认mock函数确实被调用过一次 mock_op.assert_called_once()
关键点说明
- mock
my_operation:通过patch替换真实函数,让它在测试中抛出我们指定的异常,确保my_function内的try-except逻辑被触发,而非调用真实函数导致流程直接中断。 caplogfixture:pytest内置工具,专门用于捕获日志输出,方便验证日志内容是否符合预期。pytest.raises:捕获重新抛出的异常,确保整个异常处理流程完整——捕获异常、打印日志、重新抛出。
内容的提问来源于stack exchange,提问作者aldo
相关产品推荐
相关产品推荐

