如何在 Python 测试中模拟 Awaitable
How to mock an Awaitable in Python tests
我想知道是否有一种方法可以轻松模拟 Awaitable
对象以进行 python 测试。我知道如何使用 AsyncMock
s 创建镜像协程(即从方法调用中 return Awaitable
对象),但是 运行 在尝试时遇到了一些问题直接模拟 Awaitable
。
这是一个例子:
import unittest
from asyncio import Task
from typing import Any
from unittest import IsolatedAsyncioTestCase
from unittest.mock import AsyncMock
async def function_using_awaitable(task: Task) -> Any:
await task
return task.result()
class TestFunction(IsolatedAsyncioTestCase):
async def test_function_using_awaitable(self):
mock_task = AsyncMock(spec=Task)
result = await function_using_awaitable(mock_task)
mock_task.assert_awaited_once()
assert result == mock_task.result.return_value
if __name__ == '__main__':
unittest.main()
抛出:
Traceback (most recent call last):
...
File ..., line 9, in function_using_awaitable
await task
TypeError: object AsyncMock can't be used in 'await' expression
深入研究 Python 文档,看起来 __await__
魔术方法是模拟中不支持的少数方法之一,所以想知道我该如何去做?
一个解决方案可能是将 AsyncMock 扩展为可等待的模拟对象,添加 await。在代码中,可能看起来像
from typing import Iterator, Any
async def function_using_awaitable(task: Task) -> Any:
await task
return task.result()
class AwaitableMock(AsyncMock):
def __await__(self) -> Iterator[Any]:
self.await_count += 1
return iter([])
class TestFunction(IsolatedAsyncioTestCase):
async def test_function_using_awaitable(self):
mock_task = AwaitableMock(spec=Task)
result = await function_using_awaitable(mock_task)
mock_task.assert_awaited_once()
assert result == mock_task.result.return_value
我想知道是否有一种方法可以轻松模拟 Awaitable
对象以进行 python 测试。我知道如何使用 AsyncMock
s 创建镜像协程(即从方法调用中 return Awaitable
对象),但是 运行 在尝试时遇到了一些问题直接模拟 Awaitable
。
这是一个例子:
import unittest
from asyncio import Task
from typing import Any
from unittest import IsolatedAsyncioTestCase
from unittest.mock import AsyncMock
async def function_using_awaitable(task: Task) -> Any:
await task
return task.result()
class TestFunction(IsolatedAsyncioTestCase):
async def test_function_using_awaitable(self):
mock_task = AsyncMock(spec=Task)
result = await function_using_awaitable(mock_task)
mock_task.assert_awaited_once()
assert result == mock_task.result.return_value
if __name__ == '__main__':
unittest.main()
抛出:
Traceback (most recent call last):
...
File ..., line 9, in function_using_awaitable
await task
TypeError: object AsyncMock can't be used in 'await' expression
深入研究 Python 文档,看起来 __await__
魔术方法是模拟中不支持的少数方法之一,所以想知道我该如何去做?
一个解决方案可能是将 AsyncMock 扩展为可等待的模拟对象,添加 await。在代码中,可能看起来像
from typing import Iterator, Any
async def function_using_awaitable(task: Task) -> Any:
await task
return task.result()
class AwaitableMock(AsyncMock):
def __await__(self) -> Iterator[Any]:
self.await_count += 1
return iter([])
class TestFunction(IsolatedAsyncioTestCase):
async def test_function_using_awaitable(self):
mock_task = AwaitableMock(spec=Task)
result = await function_using_awaitable(mock_task)
mock_task.assert_awaited_once()
assert result == mock_task.result.return_value