pytest-asyncio在python 3.11下报“coroutine was never awaited”警告,因pytest默认不识别async测试函数,且3.11对未await协程警告更严格;必须启用pytest-asyncio插件、配置asyncio_mode=auto,并为async测试函数添加@pytest.mark.asyncio装饰器,否则协程被创建后丢弃,测试实际未执行。

pytest-asyncio 为什么在 Python 3.11 下容易报 RuntimeWarning: coroutine 'test_foo' was never awaited
因为 pytest 默认不识别 async def 测试函数,也不会自动用事件循环执行它。Python 3.11 对未 await 的协程警告更严格,直接抛 RuntimeWarning(之前可能静默忽略)。必须显式启用 pytest-asyncio 并正确标记测试函数,否则测试会“看似通过”,实则根本没运行。
必须加 @pytest.mark.asyncio 装饰器
这是最常见漏掉的一步。仅装插件、写 async def test_xxx() 不够,pytest 不知道该用 asyncio 运行它。
-
@pytest.mark.asyncio是触发 pytest-asyncio 执行逻辑的开关,缺它就退化为普通函数(协程对象被创建后丢弃) - 装饰器可放在函数上,也可用
pytestmark = pytest.mark.asyncio放模块顶部批量标记 - 不支持对
setup_method或fixture直接加此标记——fixture 需用@pytest.fixture+scope="function"+ 显式async def,再在测试中await它
import pytest
<p>@pytest.mark.asyncio
async def test_fetch_data():
result = await fetch_from_api() # 假设这是个 async 函数
assert result == {"status": "ok"}
</p>
pytest.ini 或 pyproject.toml 中要配置 asyncio_mode = auto
Python 3.11 + pytest-asyncio 0.23+ 默认是 strict 模式,要求所有 async def 测试都带 @pytest.mark.asyncio,否则跳过并警告。设为 auto 更实用:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
-
auto:自动识别async def test_*为 asyncio 测试,无需每个都加装饰器(但仍建议加,更明确) - 配置位置优先级:命令行
--asyncio-mode=auto>pyproject.toml>pytest.ini -
pyproject.toml示例:[tool.pytest.ini_options] asyncio_mode = "auto"
fixture 中 await 协程必须显式 await,不能靠 yield 自动处理
async fixture 返回的是协程对象,不是结果。pytest-asyncio 不会自动 await 它——这和同步 fixture 完全不同。
- 错误写法:
return fetch_user()→ 返回协程,测试里拿到的是<coroutine object ...></coroutine> - 正确写法:
return await fetch_user()或yield await fetch_user() - 若 fixture 需 cleanup(比如启动/关闭服务),必须用
async def+async with或手动await teardown(),yield在 async fixture 中不触发异步 cleanup
复杂点在于:async fixture 的生命周期管理不像同步那么直觉,稍不注意就会漏 await 或错用 yield,导致资源没释放、测试间状态污染。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










