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

Python如何正确Mock urllib3.PoolManager.request方法解决单元测试报错

问题解决:urllib3 PoolManager request方法mock失效

错误原因

  • 不符合Python mock的路径规则:mock生效的前提是patch目标为业务代码实际引用的对象,你当前patch的是urllib3原生库的PoolManager.request类方法,但你的业务代码在模块顶层就已经完成了http = urllib3.PoolManager()的实例化,测试运行导入业务模块后,这个全局http实例已经创建完成,后续对类方法的patch不会作用到已存在的实例上。
  • 断言逻辑错误:@patch('urllib3.PoolManager.request')注入的mock_instance本身就是request方法的mock对象,你调用mock_instance.request.assert_called_once()相当于尝试访问mock方法的request属性,自然匹配不到实际调用。

正确实现方案

方案1:patch业务模块中已实例化的http对象的request方法

假设你的业务代码存放在service.py模块中,直接patch该模块下的全局http实例的request方法即可:

# 注意将service替换为你业务代码实际所在的模块名
@patch('service.http.request')
def test_lambda_handler(self, mock_request):
    # 配置mock返回值,注意urllib3返回的data默认是bytes类型
    mock_request.return_value = Mock(status = 200, data = b"success")
    # 执行业务函数
    res = func(event, [])
    # 直接断言mock的request方法被调用
    mock_request.assert_called_once()
    # 也可以补充断言调用参数是否符合预期
    # mock_request.assert_called_with('POST', 预期url, body=预期编码后的请求体)

方案2:调整业务代码的实例化逻辑,提升可测试性

如果不想依赖全局实例,可以将PoolManager的实例化放到函数内部,或者通过依赖注入传入,后续mock更灵活:

# 调整后的业务代码
def func(event, context, http_client=None):
    http = http_client or urllib3.PoolManager()
    # 原有业务逻辑不变
    resp = http.request('POST', url, body=encoded_msg)
    # ...

对应的测试代码不需要用patch装饰器,直接传入mock对象即可:

def test_lambda_handler(self):
    mock_http = Mock()
    mock_http.request.return_value = Mock(status=200, data=b"success")
    res = func(event, [], http_client=mock_http)
    mock_http.request.assert_called_once()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:54:01