2. 环境准备:Docker部署PostgreSQL、安装pgTAP扩展、配置测试数据库与用户权限
本章是实战案例的基础设施搭建环节。我们将通过 Docker 快速拉起 PostgreSQL 实例,安装 pgTAP 单元测试扩展,并完成测试数据库与用户权限的精细化配置。所有后续章节的 Mock 隔离场景均依赖此环境。
2.1 整体架构概览
下图展示了本次环境准备的核心组件与交互关系:Docker 容器承载 PostgreSQL 实例,内部集成 pgTAP 扩展,外部通过端口映射暴露服务,测试脚本通过专用用户连接测试数据库执行单元测试。
2.2 Docker 部署 PostgreSQL
使用官方 PostgreSQL 16 镜像,通过 Docker Compose 实现可重复的环境部署。以下为 docker-compose.yml 配置:
version: '3.8'
services:
postgres:
image: postgres:16
container_name: pg_mock_lab
restart: unless-stopped
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
volumes:
- pg_data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d
networks:
- pg_net
volumes:
pg_data:
networks:
pg_net:
driver: bridge
提示: 将初始化脚本(含 pgTAP 安装与数据库创建)放入
./init-scripts 目录,容器首次启动时会自动按文件名顺序执行。
2.3 安装 pgTAP 扩展
pgTAP 是 PostgreSQL 的单元测试框架,提供丰富的断言函数。安装方式有两种:
| 安装方式 | 命令 / 步骤 | 适用场景 |
|---|---|---|
| APT 包管理器 | apt-get install postgresql-16-pgtap |
Debian/Ubuntu 系统,快速安装 |
| 源码编译 | make && make install |
自定义 PostgreSQL 编译环境 |
| Docker 初始化脚本 | 在 init-scripts 中执行 CREATE EXTENSION pgtap; |
容器化部署,推荐方式 |
在 Docker 环境中,我们通过初始化脚本自动安装。创建 init-scripts/01-install-pgtap.sh:
#!/bin/bash
set -e
# 安装 pgTAP 扩展包
apt-get update
apt-get install -y postgresql-16-pgtap
# 连接到默认数据库并创建扩展
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION IF NOT EXISTS pgtap;
SELECT * FROM pg_extension WHERE extname = 'pgtap';
EOSQL
echo "pgTAP 扩展安装完成"
注意: 确保脚本具有可执行权限(
chmod +x),否则 Docker 不会执行。安装完成后可通过 \dx 命令验证扩展列表。
2.4 配置测试数据库与用户权限
为隔离测试环境,创建专用数据库和低权限用户。创建 init-scripts/02-create-test-db.sh:
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
-- 创建测试数据库
CREATE DATABASE unittest_db
WITH ENCODING 'UTF8'
LC_COLLATE = 'en_US.utf8'
LC_CTYPE = 'en_US.utf8'
TEMPLATE template0;
-- 创建测试用户(仅授予最小权限)
CREATE USER tester WITH PASSWORD 'testpass';
GRANT CONNECT ON DATABASE unittest_db TO tester;
GRANT USAGE ON SCHEMA public TO tester;
GRANT CREATE ON SCHEMA public TO tester;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO tester;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO tester;
-- 在测试数据库中安装 pgTAP
\c unittest_db
CREATE EXTENSION IF NOT EXISTS pgtap;
-- 验证安装
SELECT 'pgTAP installed successfully' AS status;
EOSQL
echo "测试数据库与用户配置完成"
2.5 权限矩阵与安全隔离
下表展示了不同用户在不同数据库上的权限差异,体现 Mock 测试所需的权限最小化原则:
| 用户 | 数据库 | 连接 | 读表 | 写表 | 创建对象 | 超级用户 |
|---|---|---|---|---|---|---|
| postgres | 所有 | ✓ | ✓ | ✓ | ✓ | ✓ |
| tester | unittest_db | ✓ | ✓ | ✓ | ✓ | ✗ |
| tester | postgres | ✗ | ✗ | ✗ | ✗ | ✗ |
2.6 验证环境
启动容器后,执行以下命令验证环境是否就绪:
# 启动容器
docker-compose up -d
# 验证 PostgreSQL 运行状态
docker exec pg_mock_lab pg_isready -U postgres
# 验证 pgTAP 扩展
docker exec pg_mock_lab psql -U postgres -d unittest_db -c "SELECT * FROM pg_extension WHERE extname = 'pgtap';"
# 验证用户连接
docker exec pg_mock_lab psql -U tester -d unittest_db -c "SELECT current_user, current_database();"
# 运行 pgTAP 自检
docker exec pg_mock_lab psql -U tester -d unittest_db -c "SELECT plan(1); SELECT pass('Environment is ready'); SELECT * FROM finish();"
预期输出: 最后一条命令应返回类似
1..1\nok 1 - Environment is ready 的结果,表示 pgTAP 工作正常。
2.7 环境配置清单
完成本章配置后,应获得以下环境要素:
- PostgreSQL 16 — 运行在 Docker 容器中,端口 5432 映射到宿主机
- pgTAP 扩展 v1.2.1 — 安装在
unittest_db数据库中 - 测试数据库
unittest_db— 专用测试空间,与生产数据库隔离 - 测试用户
tester— 仅拥有unittest_db的完整权限,无超级用户权限 - 初始化脚本 — 位于
init-scripts/目录,支持一键重建环境
2.8 常见问题与排错
- pgTAP 扩展创建失败: 检查是否已安装
postgresql-16-pgtap包,或手动执行CREATE EXTENSION pgtap;时是否在正确的数据库中。 - 用户连接被拒绝: 确认
pg_hba.conf中允许tester用户通过md5认证方式连接unittest_db。 - 初始化脚本未执行: 检查脚本是否具有可执行权限,文件名是否以
.sh结尾,Docker 日志中是否有错误信息。 - 端口冲突: 如果宿主机 5432 已被占用,修改
docker-compose.yml中的端口映射,例如"5433:5432"。
最佳实践: 将
docker-compose.yml 和 init-scripts/ 目录纳入版本控制,团队成员可一键复现完全一致的测试环境。