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

使用SQLAlchemy同一SessionLocal得到不同数据,pytest测试该如何修复?

问题根因

从日志打印的会话对象地址可以确认,测试用例中注入的db和接口请求触发依赖注入生成的db是两个独立的SQLAlchemy会话实例,导致跨会话数据不可见,具体原因有两个:

  • flush()方法只会将会话内的变更同步到数据库的待提交事务中,没有执行commit()的前提下,变更对其他会话完全不可见
  • 如果你使用的是SQLite内存数据库,默认配置下每个独立连接会生成一个专属内存库,两个会话对应两个独立连接,自然互相看不到数据
修复方案

方案1:统一测试环境会话实例(推荐)

这是FastAPI+SQLAlchemy测试的标准解决方案,通过依赖覆盖让接口和测试用例共用同一个会话:
在你的pytest fixture定义文件中添加如下配置:

import pytest
from fastapi.testclient import TestClient
from your_app.main import app
from your_app import deps

@pytest.fixture(scope="function")
def db():
    # 生成测试用会话
    test_db = SessionLocal()
    yield test_db
    # 测试结束后回滚所有变更,清理数据
    test_db.rollback()
    test_db.close()

@pytest.fixture(scope="function")
def client(db):
    # 重写get_db依赖,接口调用时统一返回测试用会话
    def override_get_db():
        yield db
    app.dependency_overrides[deps.get_db] = override_get_db
    yield TestClient(app)
    # 测试结束后清除依赖覆盖,避免影响其他测试
    app.dependency_overrides.clear()

修改后测试用例中注入的client和db会共用同一个会话,接口内的变更不需要提交就能直接在测试用例中查询到,测试结束后自动回滚,不会污染其他用例。

方案2:显式提交事务

如果不需要复用测试会话,你只需要在接口的crud.user.create操作后添加db.commit(),提交后的变更会对所有会话可见。注意使用该方案时,测试结束后你需要手动删除生成的测试数据,避免影响其他测试的执行。

方案3:SQLite内存库专属适配

如果你使用的是SQLite内存数据库,需要修改连接配置让所有连接共享同一个内存库:

SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:?cache=shared"

同时需要在创建引擎时添加connect_args={"check_same_thread": False}参数,关闭SQLite的同线程检查限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 19:15:03