不装 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免费学习笔记(深入)”;
- 真实 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 模式报错。别依赖“应该能识别”,显式声明才是稳的。


















