下面的示例类具有一个属性bar,与async_main()中的属性一样,因为它(理论上)在返回所有内容的答案之前做了一些IO工作。
class Foo:
@property
async def bar(self):
return 42
async def async_main():
f = Foo()
print(await f.bar)我在测试它时遇到了困难,因为Mock、MagicMock和AsyncMock的常见嫌疑并不能像预期的那样处理属性。我目前的解决办法是:
f.bar = some_awaitable()
因为这使得f.bar成为一个可以等待的“字段”,但不幸的是,在测试时,我需要多次访问它,这当然会在第二次访问时产生RuntimeError: cannot reuse already awaited coroutine。
有现成的方法来模拟这样的异步属性吗?
发布于 2022-09-25 14:50:07
我能想到的最简单的方法是再次为bar修补async属性,以便进行测试。
我假设您在Foo上有其他要测试的方法,并且该方法调用它的bar。
code.py
from asyncio import run
class Foo:
@property
async def bar(self) -> int:
return 42
async def func(self) -> int:
return await self.bar
async def main():
f = Foo()
print(await f.func())
if __name__ == '__main__':
run(main())test.py
from unittest import IsolatedAsyncioTestCase
from unittest.mock import patch
from . import code
class FooTestCase(IsolatedAsyncioTestCase):
async def test_func(self) -> None:
expected_output = 69420
@property
async def mock_bar(_foo_self: code.Foo) -> int:
return expected_output
with patch.object(code.Foo, "bar", new=mock_bar):
f = code.Foo()
# Just to see that our mocking worked:
self.assertEqual(expected_output, await f.bar)
# Should call `bar` property again:
output = await f.func()
self.assertEqual(expected_output, output)参考文献:patch docs.
https://stackoverflow.com/questions/73844248
复制相似问题