繁体   English   中英

使用unittest.mock.patch测试aiohttp客户端

[英]Testing aiohttp client with unittest.mock.patch

我用aiohttp编写了一个简单的HTTP客户端,我试图通过修补aiohttp.ClientSessionaiohttp.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)

我正在使用异步装饰器进行测试,如本答案中所述 所以这是我的尝试测试:

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)

我的is_ok协程在__main__使用时工作正常,但是当我运行测试时,它会给我一个错误,表明我的patch调用没有模拟session.request函数。 (特别是它说“无法解析来自URL'foo'的主机名”,如果它没有被模拟,它就应该这样 。)

我无法逃避这种行为。 我努力了:

  • is_ok后导入is_ok
  • 分配到嘲笑的各种组合mock_clientmock_client.__aenter__ ,设置mock_client.requestMagicMock(return_value=mock_response)或使用mock_client().request
  • 使用特定的__aenter____aexit__方法编写模拟ClientSession ,并在new参数中使用它进行patch

这些似乎没有任何区别。 如果我将断言放入is_ok来测试ClientSessionMagicMock一个实例,那么当我运行测试时这些断言就会失败(同样,当代码没有被修补时它们也会失败)。 这导致了我的命名空间不匹配理论:即,事件循环运行在patch所针对的不同命名空间中。

不管怎样,或者我做了些蠢事!

不建议使用模拟ClientSession

推荐的方法是创建虚假服务器并向其发送实际请求。

看一下aiohttp的例子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM