Mik*_*ike 6 python-3.x python-unittest python-asyncio
我尝试编写单元测试来检查类方法是否被断言。
class Application:
async def func1(self):
await self.func2(self.func3())
async def func2(self, val):
pass
async def func3(self):
pass
Run Code Online (Sandbox Code Playgroud)
并对其进行单元测试:
@pytest.mark.asyncio
async def test_method():
app = Application()
with patch.object(Application, 'func2') as mock:
await app.func1()
mock.assert_awaited_with(app.func3())
Run Code Online (Sandbox Code Playgroud)
但我收到错误:
AssertionError: expected await not found.
Expected: func2(<coroutine object Application.func3 at 0x7f1ecf8557c0>)
Actual: func2(<coroutine object Application.func3 at 0x7f1ecf855540>)
Run Code Online (Sandbox Code Playgroud)
为什么?我调用了同样的方法。我能用它做什么呢?
有一个异步测试可以更轻松地模拟(修补)异步函数。
\n\n\n\n\n打补丁
\n\n修补是一种机制,允许通过模拟就地临时替换符号\n(类、对象、函数、属性、\xe2\x80\xa6)。当需要模拟,但不能将其作为要测试的函数的参数传递时,它特别有用。
\n\n例如,如果 cache_users() 不接受客户端参数,而是创建了一个新客户端,则无法像前面所有示例那样用模拟来替换它。
\n\n当一个对象难以模拟时,它有时会显示出设计中的限制:耦合太紧、使用全局变量(或单例)等。但是,它\xe2\x80\x99s并不总是可能或不希望更改代码以适应测试。紧密耦合几乎不可见的常见情况是执行日志记录或监视时。在这种情况下,打补丁会有所帮助。
\n\npatch() 可以用作上下文管理器。它将在 with 块的生命周期内用模拟替换目标\n (logging.debug())。
\n
async def test_with_context_manager(self):\n client = asynctest.Mock(AsyncClient())\n cache = {}\n\n with asynctest.patch("logging.debug") as debug_mock:\n await cache_users_async(client, cache)\n\n debug_mock.assert_called()\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,函数的路径是作为字符串asynctest.patch而不是对象给出的。
此外,在func1 func2获取中func3作为协程并且不等待它运行(无等待)。
你可以尝试这样的事情:
\n\nimport asynctest\n@pytest.mark.asyncio\nasync def test_method():\n app = Application()\n\n with asynctest.patch(\'Application.func2\') as mock:\n await app.func1()\n mock.assert_awaited_with(app.func3())\nRun Code Online (Sandbox Code Playgroud)\n