3、集成测试环境搭建:测试数据库准备、Docker容器化数据库、连接字符串配置

集成测试环境是验证 Database Migration 正确性的基础。本章聚焦于如何快速、可重复地搭建与生产环境高度一致的测试数据库环境,涵盖物理数据库准备、Docker 容器化方案以及连接字符串的集中管理策略。

3.1 测试数据库准备策略

测试数据库的数据状态直接影响迁移脚本的验证效果。推荐采用以下三种数据准备方式,根据测试阶段灵活选择:

准备方式 适用场景 数据量级 准备速度 隔离性
基线快照恢复 冒烟测试、回归测试 中等(10万~100万行) 快(分钟级) 高
增量脚本构造 边界条件、异常场景 小(百~千行) 中(秒级) 极高
生产脱敏子集 性能验证、兼容性测试 大(百万行以上) 慢(小时级) 中
关键原则:测试数据库必须与目标迁移版本(如 MySQL 8.0 → 8.4)的字符集、排序规则、时区、sql_mode 保持一致,否则迁移脚本可能因隐式转换而失败。

3.2 Docker 容器化数据库

使用 Docker 容器化数据库可以消除“在我机器上能跑”的环境差异,实现测试环境的秒级重建。以下是标准化的容器启动流程:

  1. 拉取指定版本镜像:锁定大版本和小版本,避免意外升级。
  2. 挂载初始化脚本:将建表、造数据的 SQL 脚本挂载到容器启动目录。
  3. 配置持久化卷:将数据目录映射到宿主机,防止容器重启后数据丢失。
  4. 设置环境变量:注入 root 密码、数据库名、字符集等参数。
  5. 暴露端口:映射到宿主机非标准端口,避免与本地数据库冲突。
# 示例:启动 MySQL 8.4 测试容器
docker run -d \
  --name migration-test-db \
  -e MYSQL_ROOT_PASSWORD=TestPass123! \
  -e MYSQL_DATABASE=migration_test \
  -e MYSQL_CHARACTER_SET_SERVER=utf8mb4 \
  -e MYSQL_COLLATION_SERVER=utf8mb4_unicode_ci \
  -v /data/mysql-test:/var/lib/mysql \
  -v $(pwd)/init-scripts:/docker-entrypoint-initdb.d \
  -p 3307:3306 \
  mysql:8.4.0
最佳实践:在 CI/CD 流水线中,每次测试前执行 docker rm -f migration-test-db && docker run ...,确保测试环境完全干净,避免前序测试残留数据污染。

下图展示了 Docker 容器化数据库在集成测试环境中的完整生命周期:

Docker 容器化数据库生命周期 代码仓库 CI/CD 流水线 Docker 启动 初始化脚本 运行集成测试 容器清理 失败重试 说明: 每次测试独立容器, 环境完全隔离, 数据状态可预测。

3.3 连接字符串配置

连接字符串是测试代码与数据库之间的桥梁。在集成测试中,连接字符串必须支持多环境切换、敏感信息保护和版本兼容性。推荐使用环境变量 + 配置文件双层覆盖机制:

# config/test-database.yaml
databases:
  source:
    host: ${DB_SOURCE_HOST:-127.0.0.1}
    port: ${DB_SOURCE_PORT:-3307}
    user: ${DB_SOURCE_USER:-root}
    password: ${DB_SOURCE_PASS:-TestPass123!}
    database: ${DB_SOURCE_NAME:-migration_test}
    charset: utf8mb4
    collation: utf8mb4_unicode_ci
    ssl_mode: PREFERRED
  
  target:
    host: ${DB_TARGET_HOST:-127.0.0.1}
    port: ${DB_TARGET_PORT:-3308}
    user: ${DB_TARGET_USER:-root}
    password: ${DB_TARGET_PASS:-TestPass123!}
    database: ${DB_TARGET_NAME:-migration_test}
    charset: utf8mb4
    collation: utf8mb4_unicode_ci
    ssl_mode: PREFERRED
安全警告:切勿将明文密码提交到代码仓库。生产环境应使用密钥管理服务(如 AWS Secrets Manager、HashiCorp Vault)或 CI/CD 的 Secret 变量注入。测试环境密码建议统一为随机字符串,并在容器启动时通过环境变量传入。

连接字符串的构建逻辑通常封装在测试基类或 Fixture 中,确保所有测试用例使用统一的连接参数:

// C# 示例:从环境变量构建连接字符串
public static string BuildConnectionString(string dbType)
{
    var host = Environment.GetEnvironmentVariable($"DB_{dbType}_HOST") ?? "127.0.0.1";
    var port = Environment.GetEnvironmentVariable($"DB_{dbType}_PORT") ?? "3307";
    var user = Environment.GetEnvironmentVariable($"DB_{dbType}_USER") ?? "root";
    var pass = Environment.GetEnvironmentVariable($"DB_{dbType}_PASS") ?? "TestPass123!";
    var name = Environment.GetEnvironmentVariable($"DB_{dbType}_NAME") ?? "migration_test";
    
    return $"Server={host};Port={port};User={user};Password={pass};Database={name};Charset=utf8mb4;SslMode=Preferred;";
}

下表总结了不同数据库类型的连接字符串关键参数差异:

数据库类型 驱动/协议 端口默认值 字符集参数 SSL 参数
MySQL 8.x mysql2 / MySqlConnector 3306 Charset=utf8mb4 SslMode=Required
PostgreSQL 16 Npgsql 5432 Encoding=UTF8 SSL Mode=Require
SQL Server 2022 Microsoft.Data.SqlClient 1433 Character Set=UTF-8 Encrypt=True

3.4 环境验证清单

在正式执行迁移测试前,建议通过以下冒烟检查项验证数据库环境就绪:

  • 连通性检查:使用 telnet 或 nc 测试端口是否可达。
  • 版本一致性:执行 SELECT VERSION() 确认与目标版本一致。
  • 字符集验证:检查 character_set_server 和 collation_server 是否符合预期。
  • 权限确认:测试用户是否拥有 CREATE、ALTER、DROP、SELECT、INSERT 等必要权限。
  • 时区对齐:确认 time_zone 设置为 +00:00 或与生产环境一致。
自动化建议:将上述检查项封装为 health-check.sh 脚本,在 CI/CD 的 before_script 阶段执行,环境不通过则快速失败,避免浪费流水线资源。