Я написал простой HTTP-клиент, используя aiohttp, и пытаюсь протестировать его, исправляя aiohttp.ClientSession
и 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)
Я использую асинхронный декоратор для тестирования, как описано в этом ответе. Итак, вот мой предпринятый тест:
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 »», что должно быть, если оно не было издевательским.)
Я не могу избежать этого поведения. Я пытался:
- Импорт
is_ok
после завершения насмешек. - Различные комбинации назначения макетов для
mock_client
иmock_client.__aenter__
, установкиmock_client.request
дляMagicMock(return_value=mock_response)
или использованияmock_client().request
и т. д. - Написание макета
ClientSession
с определенными методами__aenter__
и__aexit__
и использование его в аргументеnew
дляpatch
.
Ни один из них, кажется, не имеет значения. Если я помещаю утверждения в is_ok
, чтобы проверить, что ClientSession
является экземпляром MagicMock
, то эти утверждения терпят неудачу, когда я запускаю тест (как, опять же, если код не исправлен). Это приводит меня к моей теории несоответствия пространств имен: то есть цикл событий выполняется в другом пространстве имен, на которое нацелено patch
.
Либо так, либо я делаю что-то глупое!