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

使用pytest测试时,requests的raise_for_status()为何未触发异常?

问题原因分析:mock对象未实现raise_for_status()的真实逻辑

你的测试失败核心原因是:你用mocker.Mock()创建的响应对象,只模拟了status_code属性,但没有实现raise_for_status()方法的真实行为。

具体细节:

  • 真实的requests.Response对象中,raise_for_status()方法会检查状态码:如果是4xx/5xx这类错误状态,会抛出requests.exceptions.HTTPError异常。
  • 但你测试里的mocker.Mock(status_code=500)只是一个空壳Mock对象,它的raise_for_status()方法是Mock默认生成的空方法——调用它不会做任何事,更不会抛出异常。

所以即使你看到打印的status_code是500,resp.raise_for_status()也没有触发预期的HTTPError,try块的代码会继续执行,不会进入except requests.exceptions.HTTPError分支,自然不会抛出你期望的"Not authorized"异常。

而改成直接判断status_code != 200的逻辑时,不需要依赖raise_for_status()的行为,直接读取Mock对象的status_code属性就能触发异常,所以测试能通过。

修复方案

方案1:给Mock对象添加raise_for_status()的模拟逻辑

手动让Mock的raise_for_status()在错误状态码时抛出HTTPError:

def test_raise_exception_if_request_error(requests_mock, mocker):
    mock_resp = mocker.Mock(status_code=500)
    
    # 模拟真实的raise_for_status行为
    def mock_raise():
        from requests.exceptions import HTTPError
        raise HTTPError("500 Server Error")
    mock_resp.raise_for_status = mock_raise
    
    requests_mock.return_value = mock_resp
    client = sts_api
    with pytest.raises(Exception, match='Not authorized'):
        client._get_authorize_token()

方案2:使用requests-mock库的原生模拟(更推荐)

如果你用的是requests-mock库(而不是单纯用pytest-mock的patch),它会生成真实的requests.Response实例,自动正确实现raise_for_status():

def test_raise_exception_if_request_error(requests_mock):
    # 直接用requests-mock模拟POST请求返回500
    requests_mock.post(settings.AUTHORIZATION_SERVICE_URL, status_code=500)
    client = sts_api
    with pytest.raises(Exception, match='Not authorized'):
        client._get_authorize_token()

内容的提问来源于stack exchange,提问作者Jekson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:15:37