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

如何用带参数的Fixture覆写FastAPI的app.dependency_overrides?

问题解决:让TestClient使用可回滚的SQLAlchemy Session进行集成测试

问题背景

我基于SQLAlchemy搭建了测试用的数据库连接Fixture,核心特性是会回滚事务(测试不会修改数据库):

@pytest.fixture(scope="session")
def connection():
    SQLALCHEMY_DATABASE_URL = "postgresql://{0}:{1}@{2}:{3}/{4}".format(
        settings.DB_username, settings.DB_password, settings.DB_hostname, settings.DB_port, settings.DB_name)

    engine = create_engine(
        SQLALCHEMY_DATABASE_URL,
        connect_args={"options": "-c timezone=utc"}
    )

    return engine.connect()


@pytest.fixture(scope="session")
def db_session(connection):
    transaction = connection.begin()
    yield scoped_session(
        sessionmaker(autocommit=False, autoflush=False, bind=connection)
    )
    transaction.rollback()

同时我有一个提供测试客户端的Fixture,用于从API到数据库的集成测试:

@pytest.fixture(scope='module')
def client() -> Generator:
    with TestClient(app) as c:
        yield c

目前一切正常,但问题在于应用及所有接口通过db: Session = Depends(get_db)注入数据库,客户端使用的是不会回滚的“真实”连接,导致数据库修改被持久化。

我尝试覆写get_db:

@pytest.fixture(scope='module')
def client() -> Generator:
    app.dependency_overrides[get_db] = db_session
    with TestClient(app) as c:
        yield c

但出现422错误,原因是我的配置中db_session所需的参数缺失。移除覆写语句后测试恢复正常。

请问如何用db_session(connection)覆写get_db,或如何让TestClient与其他测试使用同一个可回滚的db_session?

解决方案

问题出在直接把db_session这个fixture函数赋值给dependency_overrides,FastAPI的依赖项需要的是一个无参数的可调用对象,而db_session需要依赖connection参数,直接赋值会导致参数缺失报错。

你需要先获取已经实例化的db_session对象,再用一个无参数包装函数返回它,然后把这个函数作为依赖项覆写:

修改后的client fixture

@pytest.fixture(scope='module')
def client(db_session) -> Generator:
    # 定义无参数的生成器函数,返回已初始化的可回滚session
    def override_get_db():
        try:
            yield db_session
        finally:
            pass  # session的回滚由外层db_session fixture处理,无需手动关闭

    app.dependency_overrides[get_db] = override_get_db
    with TestClient(app) as c:
        yield c
    # 测试结束后清除依赖覆写,避免影响其他测试用例
    app.dependency_overrides.clear()

核心逻辑说明

  • client fixture现在依赖db_session,pytest会自动完成connection和db_session的初始化流程,拿到已创建好的scoped session实例
  • override_get_db是符合FastAPI依赖要求的无参数生成器,直接返回我们的可回滚session
  • 测试结束后调用app.dependency_overrides.clear(),避免该覆写影响其他测试用例

额外注意事项

  • 确保你的原get_db函数也是生成器形式(通常项目中都是这样实现):
    def get_db():
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()
    
  • 如果需要更细粒度的测试隔离(比如每个测试用例单独回滚),可以把db_session和client的scope改为function;session级别的scope在多数集成测试中性能更优,且隔离性足够

内容的提问来源于stack exchange,提问作者dermoritz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:22:39