3、集成测试环境搭建:测试数据库准备、Docker容器化数据库、连接字符串配置
集成测试环境是验证 Database Migration 正确性的基础。本章聚焦于如何快速、可重复地搭建与生产环境高度一致的测试数据库环境,涵盖物理数据库准备、Docker 容器化方案以及连接字符串的集中管理策略。
3.1 测试数据库准备策略
测试数据库的数据状态直接影响迁移脚本的验证效果。推荐采用以下三种数据准备方式,根据测试阶段灵活选择:
| 准备方式 | 适用场景 | 数据量级 | 准备速度 | 隔离性 |
|---|---|---|---|---|
| 基线快照恢复 | 冒烟测试、回归测试 | 中等(10万~100万行) | 快(分钟级) | 高 |
| 增量脚本构造 | 边界条件、异常场景 | 小(百~千行) | 中(秒级) | 极高 |
| 生产脱敏子集 | 性能验证、兼容性测试 | 大(百万行以上) | 慢(小时级) | 中 |
关键原则:测试数据库必须与目标迁移版本(如 MySQL 8.0 → 8.4)的字符集、排序规则、时区、sql_mode 保持一致,否则迁移脚本可能因隐式转换而失败。
3.2 Docker 容器化数据库
使用 Docker 容器化数据库可以消除“在我机器上能跑”的环境差异,实现测试环境的秒级重建。以下是标准化的容器启动流程:
- 拉取指定版本镜像:锁定大版本和小版本,避免意外升级。
- 挂载初始化脚本:将建表、造数据的 SQL 脚本挂载到容器启动目录。
- 配置持久化卷:将数据目录映射到宿主机,防止容器重启后数据丢失。
- 设置环境变量:注入 root 密码、数据库名、字符集等参数。
- 暴露端口:映射到宿主机非标准端口,避免与本地数据库冲突。
# 示例:启动 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 容器化数据库在集成测试环境中的完整生命周期:
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 阶段执行,环境不通过则快速失败,避免浪费流水线资源。