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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:17:45