在含异步测试的FastAPI项目中为AsyncIOMotorClient添加索引
解决方案
一、应用启动时正确创建索引
在FastAPI主文件中,利用框架提供的启动事件执行异步索引创建操作,该操作会在FastAPI管理的事件循环上下文里运行,不会出现循环错误:
from fastapi import FastAPI from your_mongo_module import mongo_instance # 替换为你的Mongo类所在模块路径 app = FastAPI() # 注册启动事件,应用启动时自动执行 @app.on_event("startup") async def init_mongo_indexes(): await mongo_instance.create_indexes()
二、修复测试场景的事件循环与索引初始化问题
1. 调整测试的事件循环与Mongo初始化Fixture
修改conftest.py,添加会话级自动执行Fixture,在测试开始前完成索引创建,同时确保事件循环正确管理:
import asyncio import pytest from your_mongo_module import mongo_instance @pytest.fixture(scope="session") def event_loop(): """创建会话级别的事件循环,避免测试间循环冲突""" loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close() @pytest.fixture(scope="session", autouse=True) async def setup_mongo_for_tests(): """测试会话开始前自动创建索引,无需手动调用""" await mongo_instance.create_indexes() yield # 可选:测试结束后可添加Mongo资源清理逻辑
2. 确保测试客户端为异步Fixture
如果你的async_clientFixture未正确定义,补充如下:
import pytest_asyncio from httpx import AsyncClient from main import app # 导入你的FastAPI应用实例 @pytest_asyncio.fixture(scope="function") async def async_client(): async with AsyncClient(app=app, base_url="http://testserver") as client: yield client
问题根源说明
- 直接在模块级别或非异步上下文里
await create_indexes():模块加载时没有活跃的事件循环,会触发循环未初始化或已关闭的错误。 - FastAPI的启动事件和测试的异步Fixture:均在框架/测试工具管理的合法事件循环中执行异步操作,可避免循环冲突问题。
内容的提问来源于stack exchange,提问作者Hossein
相关产品推荐
相关产品推荐

