Go数据库测试核心是用真实库+事务回滚/内存SQLite实现干净快速的业务逻辑验证:1.事务包裹测试并自动回滚;2.复杂场景动态建删独立库;3.SQLite内存模式用于快速CRUD验证;4.封装辅助函数统一管理生命周期。

Go 语言中为数据库逻辑写测试,关键不是“能不能连上库”,而是“能不能干净、快速、可重复地验证业务逻辑”。核心思路是:用真实数据库(如 PostgreSQL 或 SQLite)做集成测试,但通过事务回滚或临时数据库实现测试间隔离,避免数据污染和顺序依赖。
用事务包裹测试,自动回滚
这是最常用且轻量的隔离方式。每个测试开始前开启事务,执行完后强制回滚,确保不影响其他测试,也不依赖手动清理。
- 使用
db.Begin()启动事务,传入*sql.Tx给你的业务函数(需稍作改造,支持传入driver.Execer或自定义接口) - 测试主体执行完后调用
tx.Rollback()—— 即使出错也要 defer 回滚 - 注意:PostgreSQL 不支持在事务内执行
CREATE DATABASE或某些 DDL;DDL 操作建议放在测试外预置好 schema
为每个测试创建独立数据库(适合复杂场景)
当测试涉及 DDL、迁移、权限或无法用事务包裹(如某些 ORM 初始化逻辑)时,可动态创建/删除数据库。
- 用
testdb_随机字符串命名新库,通过postgres://.../postgres连接主库执行CREATE DATABASE xxx - 用
goose或golang-migrate对新库跑一次 migration - 测试结束用
DROP DATABASE清理(注意 PostgreSQL 要先断开所有连接) - 适合 CI 环境或本地开发机,不推荐在共享测试数据库上频繁建删库
用 SQLite 内存模式做快速单元测试
对纯 CRUD 和查询逻辑,SQLite 的 :memory: 模式极快且天然隔离——每个 sql.Open("sqlite3", ":memory:") 都是全新空库。
立即学习“go语言免费学习笔记(深入)”;
- 适配成本低:只要你的 SQL 是标准的(避开 PG 特有语法如
ILIKE、jsonb),就能直接复用 - 可配合
github.com/mattn/go-sqlite3+github.com/ashwanthkumar/gocql类似方案做 mock 替换 - 缺点:无法覆盖数据库特有能力,仅作为逻辑正确性初筛
封装测试辅助函数,统一管理生命周期
把重复逻辑(建库、连库、迁移、回滚/清理)抽成函数,让测试用例专注业务断言。
- 例如定义
TestDB(t *testing.T) *sql.DB,内部自动选模式(内存 / 事务 / 独立库)并注册 cleanup - 用
t.Cleanup()注册关闭或回滚动作,比手动 defer 更清晰 - 业务函数尽量接受
context.Context和Querier(如interface{ QueryContext(...), ExecContext(...) }),方便注入事务或 mock
基本上就这些。不需要抽象出复杂的 mock 层,也不必追求 100% 无数据库——用真实驱动 + 合理隔离,既保真又可控。










