golang增强标准测试包功能的插件库Testify的使用
Golang增强标准测试包功能的插件库Testify的使用
Testify是一组为Golang设计的测试工具包,提供了许多工具来验证代码行为是否符合预期。
主要功能
- 简易断言
- 模拟对象
- 测试套件接口和函数
assert包
assert
包提供了一些有用的方法,可以让你编写更好的Go测试代码。
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
// 断言相等
assert.Equal(t, 123, 123, "they should be equal")
// 断言不等
assert.NotEqual(t, 123, 456, "they should not be equal")
// 断言nil(适用于错误检查)
assert.Nil(t, object)
// 断言非nil(当你期望有值时)
if assert.NotNil(t, object) {
// 现在我们确定object不是nil,可以安全地进行进一步断言
assert.Equal(t, "Something", object.Value)
}
}
如果你需要多次断言,可以使用以下方式:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
assert := assert.New(t)
// 断言相等
assert.Equal(123, 123, "they should be equal")
// 断言不等
assert.NotEqual(123, 456, "they should not be equal")
// 断言nil
assert.Nil(object)
// 断言非nil
if assert.NotNil(object) {
assert.Equal("Something", object.Value)
}
}
require包
require
包提供了与assert
包相同的全局函数,但它们不是返回布尔结果,而是终止当前测试。这些函数必须从运行测试或基准函数的goroutine中调用,而不是从测试期间创建的其他goroutine中调用,否则可能会出现竞争条件。
mock包
mock
包提供了一种简单的机制来编写模拟对象,可以在编写测试代码时替代真实对象。
package yours
import (
"testing"
"github.com/stretchr/testify/mock"
)
/*
测试对象
*/
// MyMockedObject是一个模拟对象,实现了被测试代码依赖的接口
type MyMockedObject struct {
mock.Mock
}
// DoSomething是MyMockedObject上的方法,实现了某个接口
// 它只是记录活动,并返回Mock对象告诉它的内容
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
args := m.Called(number)
return args.Bool(0), args.Error(1)
}
/*
实际测试函数
*/
// TestSomething是一个示例,展示如何使用我们的测试对象
// 对我们正在测试的目标代码进行断言
func TestSomething(t *testing.T) {
// 创建测试对象实例
testObj := new(MyMockedObject)
// 设置期望
testObj.On("DoSomething", 123).Return(true, nil)
// 调用我们正在测试的代码
targetFuncThatDoesSomethingWithObj(testObj)
// 断言期望已满足
testObj.AssertExpectations(t)
}
suite包
suite
包提供了你可能从更常见的面向对象语言中熟悉的功能。使用它,你可以构建一个测试套件作为结构体,在结构体上构建setup/teardown方法和测试方法,并像往常一样用’go test’运行它们。
// 基本导入
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
// 定义套件,并从testify吸收内置的基本套件功能
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
}
// 确保VariableThatShouldStartAtFive在每个测试前设置为5
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
}
// 所有以"Test"开头的方法都作为套件中的测试运行
func (suite *ExampleTestSuite) TestExample() {
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}
// 为了让'go test'运行这个套件,我们需要创建一个普通的测试函数
// 并将我们的套件传递给suite.Run
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
}
安装
要安装Testify,使用go get
:
go get github.com/stretchr/testify
这将使以下包可用:
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
github.com/stretchr/testify/mock
github.com/stretchr/testify/suite
github.com/stretchr/testify/http (已弃用)
保持最新
要更新Testify到最新版本,使用go get -u github.com/stretchr/testify
。
支持的Go版本
我们目前支持从1.19开始的最新主要Go版本。
更多关于golang增强标准测试包功能的插件库Testify的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang增强标准测试包功能的插件库Testify的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Testify - Go测试增强库
Testify 是一个流行的 Go 测试增强库,它扩展了标准库 testing
的功能,提供了更强大的断言、mock 功能和测试套件支持。下面我将详细介绍 Testify 的主要组件和使用方法。
1. 安装 Testify
go get github.com/stretchr/testify
2. 主要组件
2.1 assert 包 - 强大的断言
assert 包提供了丰富的断言方法,比标准库的 t.Fail
和 t.Error
更易用。
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAdd(t *testing.T) {
result := Add(1, 2)
// 基本断言
assert.Equal(t, 3, result, "they should be equal")
assert.NotEqual(t, 4, result, "they should not be equal")
assert.Nil(t, err)
assert.NotNil(t, obj)
// 布尔断言
assert.True(t, isValid)
assert.False(t, hasError)
// 集合断言
assert.Contains(t, "Hello World", "World")
assert.Len(t, slice, 3)
assert.ElementsMatch(t, []int{1,2,3}, []int{3,2,1})
// 错误处理
assert.NoError(t, err)
assert.Error(t, err)
assert.ErrorIs(t, err, io.EOF)
}
2.2 require 包 - 致命断言
require 包与 assert 类似,但在断言失败时会立即终止测试(调用 t.FailNow()
)。
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestDivide(t *testing.T) {
result, err := Divide(10, 2)
require.NoError(t, err) // 如果出错,立即终止测试
require.Equal(t, 5, result)
}
2.3 suite 包 - 测试套件
suite 包提供了类似 xUnit 风格的测试套件功能,可以共享 setup 和 teardown 逻辑。
import (
"testing"
"github.com/stretchr/testify/suite"
)
type ExampleTestSuite struct {
suite.Suite
Value int
}
// 在每个测试前运行
func (suite *ExampleTestSuite) SetupTest() {
suite.Value = 5
}
// 测试示例
func (suite *ExampleTestSuite) TestExample() {
suite.Equal(5, suite.Value)
}
// 让go test运行这个测试套件
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
}
2.4 mock 包 - 模拟对象
mock 包提供了创建模拟对象的能力,非常适合单元测试。
import (
"testing"
"github.com/stretchr/testify/mock"
)
// 定义模拟对象
type MyMockedObject struct {
mock.Mock
}
// 模拟方法
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
args := m.Called(number)
return args.Bool(0), args.Error(1)
}
func TestSomething(t *testing.T) {
// 创建模拟对象
testObj := new(MyMockedObject)
// 设置期望
testObj.On("DoSomething", 123).Return(true, nil)
// 调用被测代码
result, err := testObj.DoSomething(123)
// 断言
assert.True(t, result)
assert.Nil(t, err)
// 验证期望是否满足
testObj.AssertExpectations(t)
}
3. 高级用法
3.1 自定义断言消息
func TestCustomMessage(t *testing.T) {
assert.Equal(t, 2, 1+1, "Math is broken!")
}
3.2 使用 assert.New 创建断言实例
func TestWithAssertInstance(t *testing.T) {
assert := assert.New(t)
// 现在可以省略第一个参数
assert.Equal(3, Add(1, 2))
assert.NotEqual(4, Add(1, 2))
}
3.3 HTTP 测试
func TestHTTPHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/hello", nil)
w := httptest.NewRecorder()
HelloHandler(w, req)
resp := w.Result()
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, _ := io.ReadAll(resp.Body)
assert.Equal(t, "Hello, World!", string(body))
}
4. 最佳实践
- 对于需要继续执行的检查使用
assert
,对于必须成功的检查使用require
- 使用测试套件组织相关测试,共享 setup/teardown 逻辑
- 为 mock 对象设置清晰的期望,并验证它们是否被满足
- 保持断言消息简洁但信息丰富
- 考虑使用
assert.New(t)
简化大量断言的测试代码
Testify 通过提供这些强大的工具,使得 Go 的单元测试更加简洁、可读和强大。它已经成为 Go 生态系统中最受欢迎的测试辅助库之一。