我遇到一个奇怪的问题,我的测试在本地通过,但是在TravisCI上失败。
我正在从第三方库中导入一个类,该类的行为需要稍作更改,因此我使用unittest.mock.patch
对其进行了修补。具体来说,我使用的对象具有一个“连接管理器”作为其类属性之一,该“连接管理器”将GET / POST / PUT处理到远程地址。此连接管理器的一个属性是requests.Session
对象,这是我需要修补的。
在创建对象时,我需要在HTTPAdapter
对象上安装新的requests.Session
,我这样做是这样的:
class CustomAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(
num_pools=connections,
maxsize=maxsize,
block=block,
assert_hostname=False)
def custom_session_function():
session = requests.Session()
session.mount(CustomHttpAdapter())
return session
def my_function():
with patch('somemodule.requests.Session', return_value=custom_session_function()):
return SomeClass()
CustomHttpAdapter
所做的全部工作是从HTTPAdapter
继承并使用PoolManager
创建assert_hostname=False
(这是将SSL连接与私有ca一起使用)
我有很多单元测试,它们使用SomeClass
对象上涉及发送HTTP请求的方法。他们只是使用requests.Session
对象并执行session.post
,依此类推。
示例类方法:
def do_post(self, path, **kwargs):
return self.session.get(
path,
params=kwargs,
headers=self.headers,
timeout=self.timeout,
verify=self.verify)
当我在本地运行它们时,所有这些都通过了,但是当我将PR提交给Travis时,当它到达与服务器通信的第一个测试时该工作将失败(该测试在docker本地在travis上运行)容器)
他们总是抱怨错误超时:
virtualenv/lib/python3.6/http/client.py:266: in _read_status raise RemoteDisconnected("Remote end closed connection without response"`
E http.client.RemoteDisconnected: Remote end closed connection without response
我很困惑,因为错误不是很描述。更令人困惑的是,以调试模式附加到Travis构建,并手动运行刚刚失败的功能似乎可以正常工作。有人知道为什么会这样吗?我不确定是否归因于我修补该对象或自定义适配器本身的方式。
编辑:附加信息。这个问题似乎是随机的。在调试版本中,我可以多次运行相同的函数,有时它可以工作,有时则不能。如果我不尝试安装定制适配器,则测试将始终通过。我更改了poolmanager,以允许每个请求多次重试,并且能够使构建一次通过,但这不是一个持久的解决方案,并且会导致构建的间歇性随机失败。
EDIT2:更奇怪的是,仅修补并返回未修改的请求。与安装自定义适配器相比,Session对象似乎会产生更多问题。
def custom_session_function():
return requests.Sesssion()
使超时发生在第一个请求上,而不是在几个请求之后。