python-3.x - 用于协程的 Python 3.8 模拟
问题描述
我尝试编写 unittest 来检查类方法是否被断言。
class Application:
async def func1(self):
await self.func2(self.func3())
async def func2(self, val):
pass
async def func3(self):
pass
并对其进行单元测试:
@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())
但我得到错误:
AssertionError: expected await not found.
Expected: func2(<coroutine object Application.func3 at 0x7f1ecf8557c0>)
Actual: func2(<coroutine object Application.func3 at 0x7f1ecf855540>)
为什么?我调用了同样的方法。我能用它做什么?
解决方案
有一个asynctest可以更轻松地模拟(修补)异步函数。
打补丁
修补是一种允许通过就地模拟临时替换符号(类、对象、函数、属性……)的机制。当需要模拟但不能将其作为要测试的函数的参数传递时,它特别有用。
例如,如果 cache_users() 不接受客户端参数,而是创建了一个新客户端,则无法像前面所有示例中那样用模拟替换它。
当一个对象难以模拟时,它有时会显示出设计中的限制:耦合太紧,使用全局变量(或单例)等。然而,更改代码并不总是可能或可取的以适应测试。紧密耦合几乎不可见的常见情况是在执行日志记录或监视时。在这种情况下,修补会有所帮助。
patch() 可以用作上下文管理器。它将在 with 块的生命周期内用模拟替换目标 (logging.debug())。
async def test_with_context_manager(self):
client = asynctest.Mock(AsyncClient())
cache = {}
with asynctest.patch("logging.debug") as debug_mock:
await cache_users_async(client, cache)
debug_mock.assert_called()
请注意,函数的路径是作为字符串asynctest.patch
而不是对象提供的。
另外,func1
func2
在gettingfunc3
作为协程并且不等待它运行(no await)。
你可以尝试这样的事情:
import asynctest
@pytest.mark.asyncio
async def test_method():
app = Application()
with asynctest.patch('Application.func2') as mock:
await app.func1()
mock.assert_awaited_with(app.func3())
推荐阅读
- reactjs - 汇总是否有将静态导入编译为动态导入的插件?
- sse - 使用 SSE 从 16 字节字段生成位掩码
- jquery - ajax 完成后再次调用 Ajax 函数
- perl - 无法为“local::lib”创建目录
- c# - XElement 替换为
- ios - 显示在 iOS 中安装应用程序时的通知计数
- java - java远程gui实现的推荐方法
- spring - @Requestmapping 中的动态 URL
- matplotlib - 在堆叠图中对齐 y 轴上的标签
- python-3.x - Python PyQt5 All text in QTextBrowser becomes 'hyperactive'