最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Golang通过Go-SQL-Mock进行数据库逻辑隔离与语言学习单元测试
时间:2026-07-24 18:10:49 编辑:袖梨 来源:一聚教程网
sqlmock.New() 默认开启严格模式,未被 Expect 的 SQL 会 panic;需显式声明所有查询、列名、事务操作及参数匹配规则,且 Expect 必须在执行前注册。
sqlmock.New() 之后为什么一执行 SQL 就 panic?
因为 sqlmock.New() 默认开启严格模式:任何没被 Expect 过的 SQL 都会立即触发 panic,比如 panic: there is no expectation for "SELECT * FROM users"。这不是 bug,是强制你显式声明所有数据库交互的设计选择。
- 别指望它自动放过健康检查语句——
db.Ping()会直接 panic,得手动写mock.ExpectQuery("SELECT 1").WillReturnRows(...) - 空格、换行、大小写都必须完全一致,
"SELECT id FROM users"和"SELECTnidnFROM users"被视为两条不同 SQL - 不确定参数(如时间戳、UUID)别硬写死,用
sqlmock.AnyArg()替代,否则匹配失败
Scan 或 StructScan 总报 “expected 3 destination arguments, not 2” 怎么办?
根本原因是 mock 返回的 rows 列定义和 Scan 目标不匹配。SQLMock 不做类型推导,只按你声明的列名和顺序严格校验。
- 必须用
sqlmock.NewRows([]string{"id", "name", "created_at"})显式声明列名,顺序、数量要和rows.Scan(&id, &name, &created_at)完全一致 - 如果用
sqlx.StructScan,struct 字段的dbtag(如db:"user_id")必须和 rows 列名完全相同;建议统一小写 + 下划线风格 - 时间字段传
time.Now()或sqlmock.NewNullTime(),别传字符串,否则类型不匹配直接报错
事务测试里 tx.Commit() 没报错但测试失败了?
SQLMock 对事务操作默认静默,tx.Commit() 是否成功,全看你有没有提前 ExpectCommit()。没 Expect 就等于“这条语句不该发生”,直接 panic。
- 每个
Begin()都必须配对ExpectBegin(),哪怕业务里嵌套了多个Begin() -
Commit和Rollback必须二选一显式 Expect,不能漏掉 -
db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})中的隔离级别会被忽略,SQLMock 只认流程,不校验选项
ExpectationsWereMet() 总是 false,但明明写了 Expect?
大概率是 Expect 注册时机错了——必须在 SQL 实际执行前注册,而不是 defer 里或函数末尾补。
立即学习“go语言免费学习笔记(深入)”;
- 常见错误:先
defer mock.ExpectationsWereMet(),再写mock.ExpectQuery(...),结果 Expect 还没注册就执行了 SQL - 同一 SQL 执行多次(比如循环查用户),就得调
mock.ExpectQuery().WillReturnRows()多次,不能只写一次 - 别在多个测试函数间复用同一个 mock 实例,每个测试应独立初始化
sqlmock.New()
最易被忽略的是列名大小写和空格——它们不像真实数据库那样宽容,差一个空格或下划线位置不对,Expect 就永远不命中。
相关文章
- 濡沫江湖各门派可采集资源物坐标点 07-24
- iCloud登录入口网页版-iCloud官网登录入口网页版 07-24
- 问剑长生2026新春游历活动满分答案大全 07-24
- 淘特官网入口-淘特网页版登录官网 07-24
- 舒舒服服小岛时光小黄花快递成就获取方式 07-24
- 伏黑甚尔暴力美学 拳拳到肉的输出手法与神级阵容搭配 07-24