go测试数据配置需按类型区分:单元测试用函数式工厂生成内存对象,集成测试用testfixtures加载数据库快照;两者混用会导致逻辑遗漏或ci变慢,且testfixtures必须指定正确dialect并避免共享数据库污染。

Go 测试数据配置没有“统一标准”,关键看测试类型:单元测试用工厂函数生成内存对象,集成测试用 testfixtures 加载真实数据库快照,两者不能混用,否则要么测不到 SQL 逻辑,要么拖慢 CI。
testfixtures.Load() 必须在事务或独立库中执行
直接对共享测试库调用 testfixtures.Load() 会导致测试间污染——它默认清空表再插入,前一个测试删了 users 表,后一个测试查不到就挂了。
- 推荐做法:每个测试用
db.Begin()开启事务,把*sql.Tx传给testfixtures.New(),测试结束调tx.Rollback() - 禁止把
*sql.DB传给多个并行测试共用,除非你确认它们互不修改同一张表 - 若必须用真实库(比如验证迁移脚本),为每个测试分配独立数据库名,如
test_db_12345,靠CREATE DATABASE+DROP DATABASE隔离
YAML 字段名必须和数据库列名完全一致
testfixtures 不做蛇形转换,CreatedAt 字段对应数据库列是 created_at,YAML 里就得写 created_at,否则静默跳过该字段,导致插入 NULL 或报错 column "xxx" of relation "yyy" does not exist。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 检查方式:用
psql -c "\d users"(PostgreSQL)或sqlite3 db.sqlite ".schema users"(SQLite)确认真实列名 - 外键字段(如
user_id)必须存在且类型匹配,否则加载顺序失败,报错类似insert or update on table "posts" violates foreign key constraint - 别依赖 struct tag
db:"created_at",它不影响 fixtures 加载
工厂函数要用 functional option 模式而非硬编码 struct
写 User{ID: 1, Name: "test", CreatedAt: time.Now()} 这类硬编码会让测试耦合、难维护,时间/UUID/递增 ID 等字段每次都要手调,一漏就干扰其他测试。
- 定义
type UserOption func(*User),实现WithID(id int64) UserOption,内部只赋值不 new - 工厂函数签名应为
func User(opts ...UserOption) *User,构建时按顺序执行所有opts,确保后写的覆盖先写的 - 嵌套结构(如
Order含User)避免循环依赖:不调User(),改用WithUser(u *User)显式注入
sqlmock 和 SQLite 内存模式不能混用
想验证 SQL 语句是否被正确构造,用 sqlmock;想验证 SQL 是否真能执行、事务是否生效、GORM tag 是否映射正确,用 SQLite :memory:。选错就卡在 CI 或测试稳定性上。
-
sqlmock必须用sqlmock.New()创建 mock DB,再传给业务函数;每条预期 SQL 都要显式mock.ExpectQuery()或mock.ExpectExec(),结尾必须mock.ExpectationsWereMet() - SQLite 内存模式需手动建表(
CREATE TABLE)、手动插入初始数据(或配合testfixtures),适合端到端验证,但无法替代 PostgreSQL 特性(如jsonb) - 事务测试必须显式
mock.ExpectBegin()和mock.ExpectRollback(),不能靠db.Begin()自动触发
最易被忽略的点是:Dialect 参数对 testfixtures 不是可选项——testfixtures.Dialect("postgres") 漏设或设错,PostgreSQL 会报 cannot truncate a table referenced in a foreign key constraint,MySQL 会报 Error 1701,SQLite 时间字段解析直接失败。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










