FastAPI+pytest批量运行测试时报Event loop is closed错误求助
解决FastAPI+pytest批量测试时"Event loop is closed"错误
问题场景
你在FastAPI应用中使用pytest编写测试,测试目录包含:
conftest.py
import pytest from fastapi.testclient import TestClient from main import app @pytest.fixture(scope="session") def test_client(): client = TestClient(app) yield client
test_cases.py
def test_get_courses(test_client): response = test_client.get("/courses/") assert response.status_code == 200 def test_get_course_overview(test_client): course_id = "66c21d35c014f6ce1d0c29ab" response = test_client.get(f"/courses/{course_id}") print(response.json()) assert response.status_code == 200
单独运行单个测试用例正常,但批量运行所有测试时,第二个测试返回500错误,响应内容为:{'status': False, 'status_code': 500, 'detail': 'Event loop is closed'}
已尝试session级fixture和pytest-asyncio,问题仍存在。
原因分析
TestClient在session级作用域下,第一个测试执行完成后,其内部管理的事件循环会被关闭。后续测试复用同一个TestClient实例时,无法再创建新的请求上下文,导致"Event loop is closed"错误。单个测试运行时,测试结束后循环关闭不会影响其他测试,因此无问题。
解决方案
方案1:将TestClient fixture改为function级作用域
每次测试都创建新的TestClient实例,避免复用已关闭循环的客户端:
修改conftest.py:
import pytest from fastapi.testclient import TestClient from main import app @pytest.fixture(scope="function") def test_client(): client = TestClient(app) yield client
这个方案简单直接,TestClient的创建成本极低,不会影响测试效率。
方案2:保留session级fixture,手动管理全局事件循环
如果需要复用session级的TestClient,可以通过自定义session级的event_loop fixture,确保整个测试会话中使用同一个未被提前关闭的事件循环:
修改conftest.py:
import pytest from fastapi.testclient import TestClient from main import app import asyncio @pytest.fixture(scope="session") def event_loop(): # 创建一个新的事件循环用于整个测试会话 loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close() @pytest.fixture(scope="session") def test_client(event_loop): client = TestClient(app) yield client
这样可以确保TestClient在整个会话中使用的是同一个持续存在的事件循环,避免循环被提前关闭。
内容的提问来源于stack exchange,提问作者putta
相关产品推荐
相关产品推荐

