assert.equal失败后继续执行,require.equal失败后立即终止测试;mock参数类型和顺序必须严格匹配原方法签名;suite中setuptest需显式调用suite.run才生效,且字段状态在测试间共享。

assert.Equal 和 require.Equal 的行为差异必须立刻厘清
断言失败后是否继续执行,不是风格偏好,而是测试逻辑安全的分水岭。用 assert.Equal 检查一个本该非空的返回值,后面紧接着访问 result.Name,一旦 result 是 nil,panic 堆栈会指向字段访问行,而非真正出问题的初始化或调用处。
-
require.Equal在失败时调用t.Fatal(),当前测试函数立即退出,不执行后续语句 -
assert.Equal仅记录错误、返回false,测试函数继续运行 - 关键前置条件(如
err == nil、配置加载成功、JSON 解析无 panic)必须用require - 多个并列字段校验(如 API 返回的
User{Name, Email, Age})适合用assert,一次看到全部偏差
mock.On 不生效?先盯紧参数类型和顺序mock.Anything 不绕过类型检查,只匹配任意值。如果被 mock 的方法签名是 Do(ctx context.Context, req <em>UserRequest)</em>,而你写成 mock.On("Do", mock.Anything, mock.Anything),但传入的是 OtherReq,根本不会命中。
- 必须严格按原方法签名顺序写
mock.On参数,类型要一致(指针/值、具体类型不能用 interface{} 替代) - 不确定时,用
mock.MatchedBy(func(v interface{}) bool { return v != nil && reflect.TypeOf(v).Name() == "UserRequest" })显式判断 - 返回值数量和类型必须与原方法完全一致;少一个
error或类型错,运行时报Wrong number or type of return values -
mock.AssertExpectations(t)必须在测试函数末尾、所有调用之后调用,提前调用会报Expected call at ... never happened
suite.Run 不调用,SetupTest 就只是普通方法testify/suite 不是自动注册机制。定义了 MySuite struct { ... } 并实现 SetupTest 后,若没在测试函数里写 suite.Run(t, new(MySuite)),那 SetupTest 和 TestXxx 方法都不会被框架调用——它们只是普通 Go 方法,不会自动触发生命周期。
-
SetupTest和TearDownTest每次测试方法执行前后各调用一次,但操作的是同一个结构体实例 - 所有测试方法共享字段状态,因此
suite默认禁用t.Parallel();并发修改同一字段会触发 data race - 若需并行,放弃
suite,改用标准t.Run+assert/require,手动管理 setup/teardown
表驱动测试中复用 assert 实例会污染 t 上下文
在 t.Run 循环外创建 a := assert.New(t),然后在每个子测试里反复调用 a.Equal,会导致所有子测试共用同一个 *testing.T 实例。一旦某个子测试失败,其错误日志和 t.Fatal 会影响其他子测试的执行和报告。
- 每个
t.Run内部必须单独调用assert.New(t) - 循环变量需显式重绑定:
tc := tc,否则闭包捕获的是循环末尾的值 - 不要用全局
assert实例,也不要在测试函数外初始化断言对象
真正容易被忽略的是:suite 共享字段带来的隐式耦合,以及 mock 参数类型检查的静默失败。这两点不靠调试器或 race detector 很难第一时间定位,往往表现为“偶尔失败”或“mock 调用不触发”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











