如何断言已记录但不影响API响应的异常?
问题:测试API内部捕获并记录的异常
场景说明
我正在测试一个API,该API内部会抛出异常,但被try-except块捕获,仅将异常记录到日志中,最终仍基于其他逻辑返回响应。API核心代码如下:
def get(self, request): # some code here try: # do something and create the response value except Exception as err: logger.exception(str(err)) return Response
测试尝试与失败
我尝试用pytest.raises检测异常是否抛出,但未成功——因为异常已被内部捕获,API最终返回值不受影响,pytest无法检测到向外抛出的异常。测试代码:
with pytest.raises(RuntimeError): response = MyInfo.as_view()(request)
测试失败结果:
> with pytest.raises(RuntimeError): E Failed: DID NOT RAISE <class 'RuntimeError'>
补充尝试:使用caplog遇到的问题
有人建议用caplog验证日志,但我的测试函数使用了@patch装饰器,以为无法传入caplog参数,于是在conftest.py中自定义了fixture:
@pytest.fixture() def my_caplog(caplog): with caplog.at_level(logging.INFO): yield print(caplog.text)
但运行后没有任何输出,不清楚该如何正确使用caplog。
解决方案
1. 让caplog与@patch共存(无需自定义fixture)
@patch和caplog可以同时作为测试函数的参数,只要保持mock参数在前,pytest fixture在后的顺序即可。示例代码:
from unittest.mock import patch import pytest import logging @patch('your_module.target_to_patch') def test_api_exception_logged(mock_target, caplog): # 设置mock抛出目标异常 mock_target.some_method.side_effect = RuntimeError("测试异常") # 构造请求并调用API request = ... # 根据你的框架构造请求对象 response = MyInfo.as_view()(request) # 验证API正常返回响应 assert response.status_code == 200 # 验证日志中存在异常记录 assert "测试异常" in caplog.text # 验证日志级别为ERROR(logger.exception默认输出ERROR级别) assert any(record.levelno == logging.ERROR for record in caplog.records)
2. 修复自定义caplog fixture
如果一定要使用自定义fixture,需注意两个问题:
logger.exception输出的是ERROR级别日志,而非INFO- 需要将caplog对象传递给测试用例,而非仅yield空上下文
修改后的fixture:
@pytest.fixture() def my_caplog(caplog): with caplog.at_level(logging.ERROR): yield caplog # 将caplog传递给测试用例
测试函数中使用:
@patch('your_module.target_to_patch') def test_api_exception_logged(mock_target, my_caplog): mock_target.some_method.side_effect = RuntimeError("测试异常") request = ... response = MyInfo.as_view()(request) assert "测试异常" in my_caplog.text assert any(record.levelno == logging.ERROR for record in my_caplog.records)
核心原理
pytest.raises仅能检测未被捕获、向外抛出的异常,你的API已通过try-except内部处理异常,因此无法用该方法检测。- 验证内部异常是否被正确记录,必须通过检查日志内容,这正是pytest的caplog fixture的作用。
内容的提问来源于stack exchange,提问作者brainoverflow
相关产品推荐
相关产品推荐

