FastAPI+Pytest测试报错:Future绑定不同事件循环
解决FastAPI异步测试中SQLAlchemy循环不匹配问题
问题根源
报错核心是异步任务与Future绑定到了不同事件循环,主要诱因:
- 异步fixture作用域不统一,部分使用session级循环、部分使用function级循环
- 同步fixture依赖异步fixture时,循环上下文不一致
- 全局依赖覆盖未在测试后清理,导致后续测试复用错误的循环绑定
修复步骤
1. 全局统一事件循环
保留session级event_loop fixture,确保所有异步操作复用同一循环:
import asyncio import pytest @pytest.fixture(scope="session") def event_loop(): loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close()
2. 调整依赖覆盖为异步fixture并清理
将同步的session_override改为异步fixture,测试完成后移除依赖覆盖,避免状态残留:
@pytest_asyncio.fixture async def session_override(db_session): async def get_session_override() -> AsyncGenerator[AsyncSession, None]: yield db_session main_app.dependency_overrides[db_helper.get_session] = get_session_override yield # 测试结束后清理覆盖 main_app.dependency_overrides.pop(db_helper.get_session, None)
3. 优化数据库会话fixture
确保数据库会话的创建、使用、销毁完全在同一循环上下文内:
@pytest_asyncio.fixture async def db_session(engine) -> AsyncGenerator[AsyncSession, None]: async with engine.begin() as connection: async with AsyncSession(bind=connection, expire_on_commit=False) as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close()
4. 验证客户端fixture依赖链
确保client fixture依赖异步的session_override,保持上下文一致:
@pytest_asyncio.fixture async def client(session_override) -> AsyncGenerator[AsyncClient, None]: async with AsyncClient(app=main_app, base_url="http://localhost:8000") as ac: yield ac
5. 修正pytest配置
确保asyncio配置强制统一循环作用域:
[tool.pytest.ini_options] # 其他配置保留不变 asyncio_mode="strict" asyncio_default_fixture_loop_scope = "session"
关键注意事项
- 所有涉及异步操作的fixture必须使用
@pytest_asyncio.fixture,避免同步/异步fixture混用导致的上下文混乱 - 必须在测试完成后清理FastAPI的依赖覆盖,防止不同测试间的状态污染
- 全程使用session级事件循环,确保所有异步任务运行在同一循环实例中
内容的提问来源于stack exchange,提问作者DenisMaslennikov
相关产品推荐
相关产品推荐

