我使用 aiohttp 编写了一个简单的 HTTP 客户端,并尝试通过修补来测试它aiohttp.ClientSession
and aiohttp.ClientResponse
。然而,看起来好像unittest.mock.patch
装饰器不尊重我的异步代码。据猜测,我会说这是某种命名空间不匹配。
这是一个最小的例子:
from aiohttp import ClientSession
async def is_ok(url:str) -> bool:
async with ClientSession() as session:
async with session.request("GET", url) as response:
return (response.status == 200)
我正在使用异步装饰器进行测试,如中所述这个答案 https://stackoverflow.com/a/23036785/876937。这是我尝试的测试:
import unittest
from unittest.mock import MagicMock, patch
from aiohttp import ClientResponse
from my.original.module import is_ok
class TestClient(unittest.TestCase):
@async_test
@patch("my.original.module.ClientSession", spec=True)
async def test_client(self, mock_client):
mock_response = MagicMock(spec=ClientResponse)
mock_response.status = 200
async def _mock_request(*args, **kwargs):
return mock_response
mock_client.request = mock_response
status = await is_ok("foo")
self.assertTrue(status)
My is_ok
协程在使用时工作得很好,比如说,__main__
,但是当我运行测试时,它给我一个错误,表明session.request
根据我的说法,函数没有被嘲笑patch
称呼。 (具体来说,它说“无法从 URL 'foo' 解析主机名”,如果它weren't嘲笑。)
我无法逃避这种行为。我努力了:
- 输入
is_ok
嘲笑完成后。
- 分配模拟的各种组合
mock_client
and mock_client.__aenter__
, 环境mock_client.request
to MagicMock(return_value=mock_response)
,或使用mock_client().request
, etc.
- 写一个模拟
ClientSession
与具体的__aenter__
and __aexit__
方法并在其中使用它new
论证patch
.
这些似乎都没有什么区别。如果我将断言放入is_ok
测试一下ClientSession
是一个实例MagicMock
,那么当我运行测试时这些断言会失败(同样,当代码未修补时它们也会失败)。这引出了我的命名空间不匹配理论:也就是说,事件循环在不同的命名空间中运行patch
正在瞄准。
要么是这样,要么我正在做一些愚蠢的事情!
Mocking ClientSession
感到气馁。
推荐的方式是创建假服务器并发送real向其提出请求。
看看aiohttp 示例 https://github.com/aio-libs/aiohttp/blob/master/examples/fake_server.py.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)