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

标签 python testing patch python-asyncio aiohttp

我已经使用 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)

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

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__ 时工作正常,但是当我运行测试时,它给我一个错误,表明 session.request 函数未根据我的 patch 调用进行模拟。 (特别是它说“无法从 URL 'foo' 解析主机名”,如果它没有被 mock ,它应该是这样。)

我无法逃避这种行为。我试过:

  • 在模拟完成后导入 is_ok
  • 将mock分配给mock_clientmock_client.__aenter__的各种组合,将mock_client.request设置为MagicMock(return_value=mock_response) ,或者使用mock_client().request
  • 使用特定的 __aenter____aexit__ 方法编写模拟 ClientSession 并在 new 参数中使用它 补丁

这些似乎都没有什么不同。如果我将断言放入 is_ok 以测试 ClientSessionMagicMock 的实例,那么当我运行测试时这些断言会失败(再次,他们会在代码未打补丁时)。这引出了我的命名空间不匹配理论:也就是说,事件循环在 patch 所针对的不同命名空间中运行。

要么那样,要么我在做一些愚蠢的事情!

最佳答案

不鼓励模拟 ClientSession

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

看看aiohttp example .

关于python - 使用 unittest.mock.patch 测试 aiohttp 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46450545/

相关文章:

python - 类型错误 : 'float' object is not callable error with bhaskara program

php - Symfony 爬虫 selectButton 方法无法获取表单

python - 这是什么补丁格式以及如何应用它

python - 从大型(密码)列表中聚合和删除重复项的有效方法

python - 在 Python 2 中比较时间

testing - 我们什么时候应该使用@InjectMocks?

c# - 编写单元测试来检查它是否实现了接口(interface)是否有意义?

python - 为什么 patch.contains_point() 在检查点是否在多边形内时与 patch.get_path().contains_point() 的行为不同?

git - 为什么 git 应用带有二进制文件的补丁而不创建二进制文件?

python - 如何使用 python3、CircleCI 和 Mayavi 对图形进行单元测试