FastAPI中Pytest依赖覆盖失效:测试仍访问生产数据库
问题:测试时依赖覆盖未生效,接口仍访问生产数据库
我在测试中希望使用测试数据库,因此采用了依赖覆盖(dependency overriding)方案,但我的接口端点仍在访问生产数据库。以下是我的代码结构及各文件代码:
代码结构
src ├── auth │ └── router.py └── main.py tests ├── conftest.py └── test_auth.py
main.py
app = FastAPI( title="Grid Bot Backend" ) routers = APIRouter(prefix="/api/v1") routers.include_router(auth_router) # 注意:需确保存在 app.include_router(routers) 才能将路由挂载到应用
auth/router.py
@router.post( "/register", summary="Create User", response_model=UserOut, dependencies=[Depends(check_user)], ) async def register_user(data: UserIn, session=Depends(get_async_session)): data.password = get_hashed_password(data.password) new_user = User(**data.dict()) session.add(new_user) await session.flush() token = create_token() new_token = Token(user_id=new_user.id, token=token) session.add(new_token) await session.commit() return UserOut(token=token, username=data.username, email=data.email)
tests/conftest.py
DATABASE_URL_TEST = f"postgresql+asyncpg://{TEST_DB_USER}..." engine = create_async_engine(DATABASE_URL_TEST) test_async_session_maker = async_sessionmaker(engine, expire_on_commit=False) async def override_get_async_session() -> AsyncGenerator[AsyncSession, None]: async with test_async_session_maker() as session: yield session app.dependency_overrides[get_async_session] = override_get_async_session @pytest.fixture(scope="session") async def ac() -> AsyncGenerator[AsyncClient, None]: async with AsyncClient(app=app, base_url="http://0.0.0.0:8000/api/v1/") as ac: yield ac
tests/test_auth.py
@pytest.mark.asyncio async def test_router_register_user(ac: AsyncClient, test_db: AsyncSession): data: UserIn = UserIn( email="test@gmail.com", username="test", password="test1234" ) body = data.dict() response = await ac.post("/auth/register", json=body) assert response.status_code == 422 or 1 == 1
解决方案
1. 确认依赖对象的一致性
确保auth/router.py中导入的get_async_session和conftest.py中覆盖的是同一个对象。比如:
- 如果
get_async_session定义在src/db.py中,两处都要通过from src.db import get_async_session导入,不能在不同位置重新定义,否则依赖覆盖会失效。
2. 确保依赖覆盖在测试前生效
将依赖覆盖逻辑放到自动执行的会话级fixture中,保证所有测试开始前完成覆盖:
# tests/conftest.py from src.main import app from src.db import get_async_session # 导入正确的依赖对象 # ... 其他数据库配置代码 ... @pytest.fixture(scope="session", autouse=True) async def setup_test_dependencies(): # 设置依赖覆盖 app.dependency_overrides[get_async_session] = override_get_async_session yield # 测试结束后清理覆盖,避免影响其他测试 app.dependency_overrides.clear() # ... 保留ac fixture ...
3. 检查FastAPI应用的路由挂载
确保main.py中已经将定义好的routers挂载到app实例上:
# main.py app.include_router(routers) # 这一行必须存在,否则路由不会被注册到应用中
4. 验证测试数据库连接
可以在override_get_async_session中添加打印,确认测试时使用的是测试数据库:
async def override_get_async_session() -> AsyncGenerator[AsyncSession, None]: print("使用测试数据库会话") # 添加验证输出 async with test_async_session_maker() as session: yield session
运行测试时如果看到该打印,说明依赖覆盖已经生效。
内容的提问来源于stack exchange,提问作者Maksim Smolovsky
相关产品推荐
相关产品推荐

