使用Pytest+SQLAlchemy+Factory Boy测试时数据无法持久化至数据库
问题根源与解决方法
问题根源
- Factory Boy的
SQLAlchemyModelFactory默认不会自动提交数据库会话,创建实例后数据仅存在于会话内存中,未写入数据库。 - 未将测试用的SQLModel会话与Factory类正确绑定,导致Factory使用的会话和API/测试查询的会话不是同一个,数据无法互通。
- 测试环境可能启用了事务自动回滚机制(如部分pytest插件的默认配置),但未正确控制提交时机,导致数据被回滚。
具体解决步骤
1. 配置Factory绑定测试会话并自动提交
创建Factory类时,指定测试用的SQLModel会话,并开启自动提交:
from factory.alchemy import SQLAlchemyModelFactory from factory import Faker from sqlmodel import Session from app.models import User # 你的SQLModel模型类 class UserFactory(SQLAlchemyModelFactory): class Meta: model = User sqlalchemy_session = test_session # 传入测试用的Session实例 sqlalchemy_session_persistence = 'commit' # 自动提交会话 name = Faker('name') email = Faker('email')
2. 确保测试会话与API会话一致
在测试的conftest.py中,通过依赖注入让API和Factory共享同一会话:
import pytest from sqlmodel import Session, create_engine, SQLModel from fastapi.testclient import TestClient from app.main import app from app.dependencies import get_db @pytest.fixture(name="session") def session_fixture(): # 连接测试用PostgreSQL库 engine = create_engine("postgresql://user:password@localhost/test_db") SQLModel.metadata.create_all(engine) with Session(engine) as session: yield session SQLModel.metadata.drop_all(engine) @pytest.fixture(name="client") def client_fixture(session: Session): def override_get_db(): yield session app.dependency_overrides[get_db] = override_get_db yield TestClient(app) app.dependency_overrides.clear()
测试时将session传入Factory的Meta配置,或在Factory中动态获取该会话。
3. 手动提交会话(可选)
若不需要Factory自动提交,可在创建实例后手动提交会话:
def test_get_users(client: TestClient, session: Session): # 动态绑定会话到Factory UserFactory._meta.sqlalchemy_session = session UserFactory() session.commit() # 手动提交到数据库 response = client.get("/users/") assert response.status_code == 200 assert len(response.json()) == 1
4. 检查事务回滚配置
如果使用了自动回滚的pytest插件,可在需要持久化的测试中临时禁用回滚,或确保提交操作在API调用前完成。
内容的提问来源于stack exchange,提问作者João Pedro Martins de Paula
相关产品推荐
相关产品推荐

