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

Flask-SQLAlchemy+MariaDB数据库Mock:库未创建时create_all报错的解决方法

解决Flask+unittest测试MariaDB时数据库不存在的问题

因为MariaDB是服务器型数据库,不像SQLite会自动创建数据库文件,所以必须先手动创建测试数据库,再操作表。可以通过以下步骤实现:

核心思路

  1. 在setUp()中,先连接到MariaDB的默认系统数据库(比如mysql),执行创建测试数据库的SQL语句。
  2. 再调用db.create_all()创建业务表。
  3. 在tearDown()中,先删除业务表,再删除测试数据库。

具体实现代码

修改测试类,拆分数据库连接信息并手动管理测试库的创建/删除:

import unittest
from sqlalchemy import create_engine
from flask import current_app
from app import create_app, db

class BasicsTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()
        
        # 从配置中拆分数据库连接信息
        db_uri = self.app.config['SQLALCHEMY_DATABASE_URI']
        split_uri = db_uri.split('/')
        test_db_name = split_uri[-1].split('?')[0]
        # 构建连接系统数据库(mysql)的URI
        system_db_uri = '/'.join(split_uri[:-1]) + '/mysql'
        if '?' in split_uri[-1]:
            system_db_uri += '?' + split_uri[-1].split('?')[1]
        
        # 连接系统库,创建测试数据库
        system_engine = create_engine(system_db_uri)
        with system_engine.connect() as conn:
            conn.execution_options(isolation_level="AUTOCOMMIT")
            conn.execute(f"CREATE DATABASE IF NOT EXISTS {test_db_name}")
        
        # 现在可以正常创建业务表
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        
        # 连接系统库,删除测试数据库
        db_uri = self.app.config['SQLALCHEMY_DATABASE_URI']
        split_uri = db_uri.split('/')
        test_db_name = split_uri[-1].split('?')[0]
        system_db_uri = '/'.join(split_uri[:-1]) + '/mysql'
        if '?' in split_uri[-1]:
            system_db_uri += '?' + split_uri[-1].split('?')[1]
        
        system_engine = create_engine(system_db_uri)
        with system_engine.connect() as conn:
            conn.execution_options(isolation_level="AUTOCOMMIT")
            conn.execute(f"DROP DATABASE IF EXISTS {test_db_name}")
        
        self.app_context.pop()

关键说明

  • 确保使用的数据库账号(比如示例中的admin)拥有创建、删除数据库的权限。
  • 添加IF NOT EXISTS和IF EXISTS避免重复操作的报错。
  • 设置isolation_level="AUTOCOMMIT"是因为创建/删除数据库的语句无法在事务中执行,需要立即生效。

进阶替代方案

如果想完全隔离测试环境,不用手动管理数据库生命周期,可以使用Testcontainers库:它会在测试启动时自动拉起临时的MariaDB容器,测试结束后自动销毁容器,适合复杂测试场景,不过需要额外安装依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:30:34