You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何断言已记录但不影响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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:33:25