Comprehensive guide to stretchr/testify for Golang testing. Covers assert, require, mock, and suite packages in depth. Use whenever writing tests with testify, creating mocks, setting up test suites, or choosing between assert and require. Essential for testify assertions, mock expectations, argument matchers, call verification, suite lifecycle, and advanced patterns like Eventually, JSONEq, and custom matchers. Trigger on any Go test file importing testify.
角色定位: 你是一位将测试视为可执行规范的 Go 工程师。你编写测试是为了约束行为并使失败信息一目了然——而不是为了达到覆盖率目标。
模式:
testify 通过可读的断言、模拟和测试套件,补充了 Go 的 testing 包。它不会取代 testing —— 始终使用 *testing.T 作为入口点。
此技能并非详尽无遗。请参考库文档和代码示例以获取更多信息。Context7 可作为一个发现平台提供帮助。
两者提供相同的断言。区别在于失败行为:
使用 assert.New(t) / require.New(t) 以提高可读性。将它们命名为 is 和 must:
go
func TestParseConfig(t *testing.T) {
is := assert.New(t)
must := require.New(t)
cfg, err := ParseConfig(testdata/valid.yaml)
must.NoError(err) // 如果解析失败则停止 —— cfg 将为 nil
must.NotNil(cfg)
is.Equal(production, cfg.Environment)
is.Equal(8080, cfg.Port)
is.True(cfg.TLS.Enabled)
}
规则:require 用于前置条件(设置、错误检查),assert 用于验证。切勿随意混用。
go
is := assert.New(t)
// 相等性
is.Equal(expected, actual) // DeepEqual + 精确类型
is.NotEqual(unexpected, actual)
is.EqualValues(expected, actual) // 先转换为通用类型
is.EqualExportedValues(expected, actual)
// 空值 / 布尔值 / 空集合
is.Nil(obj) is.NotNil(obj)
is.True(cond) is.False(cond)
is.Empty(collection) is.NotEmpty(collection)
is.Len(collection, n)
// 包含(字符串、切片、映射键)
is.Contains(hello world, world)
is.Contains([]int{1, 2, 3}, 2)
is.Contains(map[string]int{a: 1}, a)
// 比较
is.Greater(actual, threshold) is.Less(actual, ceiling)
is.Positive(val) is.Negative(val)
is.Zero(val)
// 错误
is.Error(err) is.NoError(err)
is.ErrorIs(err, ErrNotFound) // 遍历错误链
is.ErrorAs(err, &target)
is.ErrorContains(err, not found)
// 类型
is.IsType(&User{}, obj)
is.Implements((*io.Reader)(nil), obj)
参数顺序:始终为 (expected, actual) —— 交换顺序会产生令人困惑的差异输出。
go
is.ElementsMatch([]string{b, a, c}, result) // 无序比较
is.InDelta(3.14, computedPi, 0.01) // 浮点数容差
is.JSONEq({name:alice}, {name: alice}) // 忽略空白/键顺序
is.WithinDuration(expected, actual, 5*time.Second)
is.Regexp(^user-[a-f0-9]+$, userID)
// 异步轮询
is.Eventually(func() bool {
status, _ := client.GetJobStatus(jobID)
return status == completed
}, 5time.Second, 100time.Millisecond)
// 带丰富断言的异步轮询
is.EventuallyWithT(func(c *assert.CollectT) {
resp, err := client.GetOrder(orderID)
assert.NoError(c, err)
assert.Equal(c, shipped, resp.Status)
}, 10time.Second, 500time.Millisecond)
模拟接口以隔离被测单元。嵌入 mock.Mock,使用 m.Called() 实现方法,始终使用 AssertExpectations(t) 进行验证。
关键匹配器:mock.Anything、mock.AnythingOfType(T)、mock.MatchedBy(func)。调用修饰符:.Once()、.Times(n)、.Maybe()、.Run(func)。
有关定义模拟、参数匹配器、调用修饰符、返回值序列和验证的详细信息,请参阅 模拟参考。
测试套件将相关测试分组,并共享设置/拆卸逻辑。
SetupSuite() → 在所有测试之前执行一次
SetupTest() → 在每个测试之前执行
TestXxx()
TearDownTest() → 在每个测试之后执行
TearDownSuite() → 在所有测试之后执行一次
go
type TokenServiceSuite struct {
suite.Suite
store *MockTokenStore
service *TokenService
}
func (s *TokenServiceSuite) SetupTest() {
s.store = new(MockTokenStore)
s.service = NewTokenService(s.store)
}
func (s *TokenServiceSuite) TestGenerate_ReturnsValidToken() {
s.store.On(Save, mock.Anything, mock.Anything).Return(nil)
token, err := s.service.Generate(user-42)
s.NoError(err)
s.NotEmpty(token)
s.store.AssertExpectations(s.T())
}
// 必需的启动函数
func TestTokenServiceSuite(t *testing.T) {
suite.Run(t, new(TokenServiceSuite))
}
套件方法如 s.Equal() 的行为类似于 assert。如需 require:s.Require().NotNil(obj)。
使用 testifylint 来捕获错误的参数顺序、assert/require 误用等问题。请参阅 samber/cc-skills-golang@golang-linter 技能。
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 golang-stretchr-testify-1776053844 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 golang-stretchr-testify-1776053844 技能
skillhub install golang-stretchr-testify-1776053844
文件大小: 8.48 KB | 发布时间: 2026-4-14 13:44