使用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
相关产品推荐
相关产品推荐

