跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

Python3.11异步代码怎么进行单元测试_pytest-asyncio插件实战应用

不装 pytest-asyncio 插件,async def 测试函数会被当作普通函数调用而不 await,仅报“was never awaited”警告且显示“passed”,实际未执行;必须安装插件、配置 asyncio_mode = auto、标记 @pytest.mark.asyncio,禁用手动 event loop 操作。 直接上结论:不装
pytest-asyncio
,所有
async def
测试函数都会被当成普通函数调用,协程对象创建后根本没
await
,只报
RuntimeWarning: coroutine 'test_xxx' was never awaited
,测试还显示“passed”——实际什么都没执行。 pytest 运行 async test 报 “was never awaited” 怎么办 这不是代码写错了,是 pytest 默认根本不认识
async def
。它看到函数就直接调,不启动 event loop,也不 await 协程。 必须安装插件:
pip install pytest-asyncio
必须在配置文件中启用并设模式:
asyncio_mode = auto
(写在
pytest.ini
或
pyproject.toml
里) 必须给测试函数加标记:
@pytest.mark.asyncio
(尤其在
class
内或用了 fixture 时,不加会跳过或报错) 别手动写
asyncio.run()
或
loop.run_until_complete()
—— 插件已封装好干净的 event loop 实例,重复干预反而引发
Event loop is closed
async fixture 怎么写才不爆错 异步 fixture 不能用
yield
,不能返回 generator,也不能混用同步逻辑;否则 pytest-asyncio 无法调度,运行时直接抛
TypeError: object ... can't be used in 'await' expression
。 必须用
async def
定义 必须用
return
(不是
yield
),例如:
return await create_test_db()
调用处必须
await
它,比如在测试函数里写
db = await db_fixture
如果 fixture 被多个 test 共享,建议加
scope="function"
,避免 loop 状态污染 为什么 async 测试跑得比同步还慢 不是 asyncio 慢,是你在 test 里偷偷发了真实请求、连了 DB、或者写了
await asyncio.sleep(1)
—— 这些都会让单个测试卡住 1 秒,批量跑就彻底不可控。 Python 3.14.3 微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。 下载 立即学习 “ Python免费学习笔记(深入) ”; 真实 IO 必须 mock:优先 patch 被测函数内部 import 的路径,比如
myapp.clients.http_client.fetch
,而不是
aiohttp.ClientSession.get
(容易因 import 方式不同漏掉)
asyncio.sleep
必须替换为
asyncio.sleep(0)
或直接删掉;若需模拟延迟,用
async_mock
控制返回时机 别用
patch
去 mock 整个模块,容易因相对导入/绝对导入路径不一致导致 mock 失效 调试 async test 断点进不去怎么办
breakpoint()
在 async 函数里默认不生效,因为 pdb 不知道怎么挂起协程上下文。 最简方案:加
@pytest.mark.asyncio
后直接运行
pytest --pdb test_file.py::test_name
,pytest-asyncio 会把断点接入 event loop VS Code 用户:确保
launch.json
中
"justMyCode": true
且 Python 扩展已启用 asyncio 支持 避免手动
import pdb; pdb.set_trace()
—— 在未激活 asyncio 调试上下文时,它会卡死或跳过 最容易被忽略的是配置文件里漏写
asyncio_mode = auto
:新版本 pytest 不再自动启用插件,即使装了、加了 mark,没这行配置,async test 就是会被静默跳过或按 strict 模式报错。别依赖“应该能识别”,显式声明才是稳的。

相关文章