应使用testify/assert替代原生t.errorf手动断言,因assert.equal一行完成深比较并输出清晰差异,require.noerror用于前置校验并立即终止;需先求值再断言、用jsoneq校验json、表驱动测试加case前缀。

为什么直接用 t.Errorf 写断言容易出错
因为每写一次 if got != want { t.Errorf(...) },都要手动拼接错误信息、处理类型、考虑是否继续执行。更麻烦的是:一旦漏掉 t.Helper(),报错行号就指向封装函数内部,而不是你真正写测试的那行;如果在循环里用 t.Error 累积失败,最后可能看到一堆无关紧要的错误,而关键初始化失败却被淹没。
assert.Equal 和 require.NoError 的实际分工
它们都来自 github.com/stretchr/testify,但行为差异直接影响测试稳定性:
-
assert.Equal(t, want, got)失败只记录错误,测试函数继续执行——适合校验多个字段或并列条件 -
require.NoError(t, err)失败直接终止当前测试函数——适合前置检查,比如数据库连接、JSON 解析、文件打开等不可恢复步骤 - 两者都做深比较,但
assert.Equal对nilslice 和空 slice 判为相等,reflect.DeepEqual不会 - 所有
assert.Xxx函数返回bool,但默认不中断;若需链式判断(如先断言非 nil 再取字段),必须用require.Xxx
封装自己的 assertPanic 辅助函数要注意什么
Go 没有原生 panic 断言,靠 recover 捕获,但裸写极易翻车:
- 必须在被测函数调用前设
defer,且recover()要放在 defer 里,不能提前赋值 - 辅助函数第一行必须加
t.Helper(),否则t.Fatal报错位置错乱 - 别把待测函数和
recover写在同一作用域,例如func() { f(); recover() }()是无效的——panic 已经退出当前 goroutine - 如果被测函数本身调用
os.Exit或向 os.Stdin 写入,recover捕获不到,得换集成测试方式
HTTP 接口测试中别用 assert.Equal 直接比响应字符串
API 返回体含时间戳、随机 ID 或字段顺序不固定时,字符串比对必然失败:
- 改用
assert.JSONEq(t, wantJSON, string(body)),它会解析两边 JSON 后语义比对,忽略空格、键序、float 小数位差异 - 但输入必须是合法 JSON,非法字符串会让
JSONEqpanic,建议先用json.Valid预检 - 若响应含动态字段(如
"created_at": "2026-06-23T02:13:00Z"),先用strings.ReplaceAll或正则替换再喂给JSONEq,不要试图在 JSON 字符串里写模糊匹配 - 状态码、Header 必须单独断言,
JSONEq只管 body
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











