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

如何在Flask与SQLAlchemy项目中正确使用pytest进行测试?

Flask + SQLAlchemy + Pytest 测试套件解决方案(实例注册错误修复)

错误根源

你的测试代码中,conftest.py创建了全新的SQLAlchemy实例,但app/models.py里的User模型绑定的是主应用中的db实例,两者不匹配导致ORM无法识别当前应用上下文对应的数据库实例,从而抛出注册错误。

完整可运行实现方案

项目结构

your_project/
├── app/
│   ├── __init__.py
│   └── models.py
├── tests/
│   ├── conftest.py
│   └── test_db.py
└── requirements.txt

1. 主应用核心代码

app/__init__.py(统一数据库实例):

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# 全局共享的SQLAlchemy实例,主应用和测试复用
db = SQLAlchemy()

def create_app(config_class=None):
    app = Flask(__name__)
    if config_class:
        app.config.from_object(config_class)
    
    # 用全局db实例初始化应用
    db.init_app(app)
    return app

app/models.py(绑定全局db实例):

from app import db

class User(db.Model):
    id = db.Column(db.String(20), primary_key=True)
    username = db.Column(db.String(50), nullable=False)
    
    def __repr__(self):
        return f'<User {self.username}>'

2. 测试夹具配置

tests/conftest.py:

import pytest
from app import create_app, db
from app.models import User

class TestConfig:
    SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
    TESTING = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False

# 函数级夹具:每个测试用例都获取干净的应用和数据库
@pytest.fixture(scope="function")
def app():
    app = create_app(TestConfig)
    
    with app.app_context():
        db.create_all()
        # 预置测试数据
        test_user = User(id="0", username="test_user")
        db.session.add(test_user)
        db.session.commit()
        yield app
        # 清理资源
        db.session.remove()
        db.drop_all()

# 可选:提供测试客户端夹具
@pytest.fixture(scope="function")
def client(app):
    return app.test_client()

# 可选:提供数据库会话夹具
@pytest.fixture(scope="function")
def db_session(app):
    with app.app_context():
        yield db.session
        db.session.rollback()

3. 测试用例示例

tests/test_db.py:

from app.models import User

def test_existing_user_query(app):
    with app.app_context():
        user = User.query.filter_by(id="0").first()
        assert user is not None
        assert user.username == "test_user"

def test_create_new_user(db_session):
    new_user = User(id="1", username="new_test_user")
    db_session.add(new_user)
    db_session.commit()
    
    user = User.query.get("1")
    assert user.username == "new_test_user"

关键注意事项

  • 共享数据库实例:主应用和测试必须使用同一个SQLAlchemy实例,避免多实例不匹配问题
  • 函数级隔离:使用scope="function"确保每个测试用例都有独立的数据库环境,避免测试间数据污染
  • 上下文管理:所有数据库操作必须在应用上下文(app.app_context())中执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:25:07