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

Flask单元测试配置临时数据库后仍访问开发数据库

问题原因与解决方案

问题根源

  • 根目录app.py提前执行了create_app()并初始化了Migrate,导致db实例已经和开发环境的Flask应用绑定,测试时导入的_db是已关联MySQL连接的实例。
  • setUp中修改_app配置的时机太晚:db.init_app(app)在create_app执行时已经完成初始化,db已绑定初始的MySQL配置,后续修改应用配置不会同步更新db的连接信息。
  • 测试直接复用了开发环境的应用实例,没有创建独立的测试专用应用。

修复步骤

1. 调整根目录app.py结构,避免提前初始化开发应用

将应用初始化逻辑移到if __name__ == '__main__':代码块内,确保只有直接运行app.py时才会启动开发环境,测试导入该文件时不会提前创建应用:

from flask_migrate import Migrate
from dotenv import load_dotenv
import os
from src.app import create_app, db

load_dotenv()

if __name__ == '__main__':
    app = create_app()
    Migrate(app, db)
    app.run()

2. 修改测试文件,创建独立的测试应用

测试时应生成全新的应用实例,绑定内存SQLite数据库,避免影响开发数据库。有两种实现方式:

方式一:直接在测试中修改配置并重新初始化DB

import unittest
from src.app import create_app, db as _db
import json

class BaseTest(unittest.TestCase):
    @classmethod
    def setUp(cls) -> None:
        # 创建全新的测试应用实例
        cls.app = create_app()
        # 覆盖为测试数据库配置
        cls.app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///:memory:"
        cls.app.config['TESTING'] = True
        
        # 将DB与测试应用重新绑定
        with cls.app.app_context():
            _db.init_app(cls.app)
            _db.drop_all()
            _db.create_all()
            cls.client = cls.app.test_client()

方式二:让create_app支持配置覆盖(更优雅)

先修改src/app.py的create_app函数,允许传入配置覆盖默认值:

def create_app(config_overrides=None):
    app = Flask(__name__)
    # 基础开发配置
    app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{db_user}:{db_pass}@{db_host}:{db_port}/{db_name}'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['DEBUG'] = True
    
    # 应用传入的测试配置
    if config_overrides:
        app.config.update(config_overrides)
    
    register_extensions(app)
    from src.apis import register_models
    register_blueprints(app)
    configure_databse(app)
    return app

然后在测试中直接传入测试配置创建应用:

import unittest
from src.app import create_app, db as _db
import json

class BaseTest(unittest.TestCase):
    @classmethod
    def setUp(cls) -> None:
        # 直接传入测试配置创建应用
        cls.app = create_app({
            'SQLALCHEMY_DATABASE_URI': "sqlite:///:memory:",
            'TESTING': True
        })
        
        with cls.app.app_context():
            _db.drop_all()
            _db.create_all()
            cls.client = cls.app.test_client()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:42:05