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

requests_mock作为pytest fixture拦截未设置请求报错问题求助

解决requests-mock fixture拦截所有请求的问题

我来帮你理清这个问题——这其实不是bug,是requests-mock fixture的默认行为:它会拦截所有通过requests库发起的请求,哪怕你没给对应URL设置mock规则。下面分两种场景给你解决方案:

一、让特定URL绕过mock,走真实网络请求

如果你希望https://api-b.com/的请求不被拦截,直接走真实接口,可以通过以下两种方式实现:

方法1:给目标URL添加带real_http=True的mock规则

在测试代码里,给https://api-b.com/添加一个允许真实请求的规则,这样requests-mock就会放行这个URL的所有请求:

def test_reqs(requests_mock):
    # Mock api-a的请求
    requests_mock.get('https://api-a.com/')
    # 放行api-b的所有请求,走真实网络
    requests_mock.get('https://api-b.com/', real_http=True)
    
    # 现在这个请求会走真实接口,不会被拦截报错
    requests.get('https://api-b.com/')
    assert requests.get('https://api-a.com/')

如果api-b有多个路径,也可以用通配符匹配所有子路径:

requests_mock.get('https://api-b.com/*', real_http=True)

方法2:全局启用真实请求(不推荐,除非大部分请求都需要真实调用)

如果你的测试里大部分请求都需要走真实网络,只有少数需要mock,可以直接给requests-mock对象设置全局真实请求开关:

def test_reqs(requests_mock):
    requests_mock.real_http = True
    # 只mock需要拦截的api-a
    requests_mock.get('https://api-a.com/')
    
    requests.get('https://api-b.com/')  # 走真实请求
    assert requests.get('https://api-a.com/')

二、解决第三方模块内部调用被拦截的问题

第三方模块内部用requests发起的请求也会被requests-mock拦截,这是因为requests-mock是通过patchrequests.Session.send实现全局拦截的。解决思路有两种:

思路1:给第三方模块调用的URL放行(推荐)

和上面的方法一样,只要知道第三方模块调用的目标URL,给它添加real_http=True的规则即可:

def test_third_party(requests_mock):
    # Mock你的业务接口依赖的api-a
    requests_mock.get('https://api-a.com/')
    # 放行第三方模块调用的api-b
    requests_mock.get('https://api-b.com/', real_http=True)
    
    # 调用第三方模块的方法,它内部的api-b请求会走真实网络
    third_party_module.some_function()

思路2:绕过requests-mock,直接mock第三方模块的方法

如果不想依赖requests-mock的URL规则,可以用pytest-mock直接mock第三方模块的具体方法,而不是mockrequests本身。比如第三方模块third_party里有个call_api方法内部调用了requests.get('https://api-b.com/'),你可以直接mock这个call_api方法:

def test_third_party(mocker):
    # Mock第三方模块的方法,返回你需要的模拟结果
    mocker.patch('third_party.call_api', return_value={'data': 'fake_response'})
    # 同时用requests-mock上下文管理器mock你的api-a
    from requests_mock import Mocker
    with Mocker() as m:
        m.get('https://api-a.com/')
        # 执行你的业务逻辑测试
        your_service.process_data()

这种方法的好处是完全隔离第三方模块的请求,不需要关心它内部用了哪个URL,但前提是你能明确第三方模块的调用入口。

总结一下

requests-mock的全局拦截是设计如此,不是bug。你只需要通过real_http=True规则放行不需要mock的URL,或者针对第三方模块的方法直接mock,就能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:18:10