You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pytest-asyncio测试FastAPI路由报Event loop is closed错误

问题现象

测试用例中发起超过1次异步调用时,固定触发如下报错:

RuntimeError: Event loop is closed

已尝试参考通用方案重写event_loop fixture,所有调整均未生效,需排查遗漏的配置点。

现有配置信息
  • 测试执行命令:
python -m pytest tests/ --asyncio-mode=auto
  • 依赖版本(requirements.txt):
pytest==7.1.2
pytest-asyncio==0.18.3
pytest-html==3.1.1
pytest-metadata==2.0.1
  • 测试用例代码(test.py):
async def test_user(test_client_fast_api):
    assert 200 == 200

    # 首次接口调用正常
    request_first = test_client_fast_api.post("/first_route")

    # 第二次接口调用触发 RuntimeError: Event loop is closed
    request_second = test_client_fast_api.post("/second_route")
  • 自定义fixture代码(conftest.py):
@pytest.fixture()
def event_loop():
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        loop = asyncio.new_event_loop()
    yield loop
    loop.close()
问题根因
  1. 自定义event_loop fixture默认使用函数级作用域,和FastAPI测试客户端test_client_fast_api的生命周期不匹配:首次请求执行完成后,函数级的event_loop fixture就会执行teardown逻辑关闭事件循环,第二次请求发起时已经没有可用的运行中事件循环。
  2. 现有event_loop逻辑存在缺陷:asyncio.get_running_loop()会抓取当前上下文已存在的运行中循环(可能是其他fixture/框架持有的循环),teardown阶段强制关闭该循环会直接破坏其他组件的正常运行。
  3. pytest-asyncio 0.18.3版本在--asyncio-mode=auto模式下不会主动校验异步fixture的作用域匹配关系,不会抛出显性的生命周期不匹配错误,只会静默触发事件循环关闭异常。
修复方案
  1. 调整event_loop fixture的作用域,和test_client_fast_api的作用域保持完全一致(如果测试客户端是会话级fixture就设为scope="session",模块级就设为scope="module"),不要使用默认的函数级作用域。
  2. 重写event_loop逻辑,不要抓取外部已有的运行中循环,直接为fixture创建专属的事件循环,随fixture生命周期统一创建和销毁,参考代码:
@pytest.fixture(scope="session") # 作用域和test_client_fast_api对齐
def event_loop():
    loop = asyncio.new_event_loop()
    yield loop
    loop.close()
  1. 校验test_client_fast_api的fixture定义,确保其显式依赖event_loop,且二者作用域完全一致,避免出现生命周期错位。

内容的提问来源于stack exchange,提问作者Dmitriy_kzn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:51:34