Go单元测试利器testify使用示例详解

目录
  • testify
    • assert 包
    • require 包
    • mock 包
    • suite 包

testify

在团队里推行单元测试的时候,有一个反对的意见是:写单元测试耗时太多。且不论这个意见对错,单元测试确实不应该太费时间。这时候,一个好的单测辅助工具,显得格外重要。本文推荐的 testify(github.com/stretchr/te…) 包,具有断言、mock 等功能,能配合标准库,使你的单元测试更加简洁易读。

testify 有三个主要功能:

  • 断言,在 assert 包和 require 包。
  • Mocking,在 mock 包下。
  • 测试组件,在 suite 包下。

assert 包

assert 包提供了一系列很方便的断言方法,简化你的测试代码。如

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)
}

assert 包的函数的第一个参数为 testing.T,用于执行 go test 时输出信息。

如果你有很多个断言,可以调用New方法实例化 Assertions 结构体,然后就可以省略testing.T参数了。上面的代码,可以简化成

func TestSomething(t *testing.T) {
  // 实例化 assertion 结构体,下面的断言都不用传入 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)
}

assert 失败的话,底层调用 t.Errorf 来输出错误信息。也就是说,断言失败并不会中停止测试。

assert 包的断言函数,返回值是 bool 类型,表示断言的成功或失败。 我们可以根据返回值,进一步做断言。如

// 当 object 不为 nil 的时候,进一步断言 object.Value 的值
if assert.NotNil(t, object) {
  assert.Equal(t, "Something", object.Value)
}

assert 包提供的断言类型非常多,包括对比变量、json、目录、Http 响应等。完整列表见:pkg.go.dev/github.com/…

require 包

require 包提供的函数和 assert 包是一样的,区别是:

  • require 包如果断言失败,底层调用 t.FailNow, 会立刻中断当前的测试,所以也不会有返回值。
  • assert 包如果断言失败,底层调用 t.Errorf,返回 false,不会中断测试。

mock 包

单元测试一般仅限于测试本服务,对于别的服务的调用(比如数据库),我们可以创建 Mock 对象来模拟对其他服务的调用。

和别的语言一样,Mock 对象我们可以通过工具自动生成。mockery(github.com/vektra/mock…) 工具可以根据 golang 的 interface,生成类似下面的 Mock 对象。

package yours
import (
  "testing"
  "github.com/stretchr/testify/mock"
)
// Mock 对象,会依赖 mock.Mock
type MyMockedObject struct{
  mock.Mock
}
// 要 mock 的接口的方法
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
  args := m.Called(number)
  return args.Bool(0), args.Error(1)
}

我们可以调用 Mock 对象的 On 方法,设置对应方法的参数和返回值。如

// 测试
func TestSomething(t *testing.T) {
  // 实例化 Mock 对象
  testObj := new(MyMockedObject)
  // 设置预期,当调用 testObj.DoSomething(123)时,返回 true, nil
  testObj.On("DoSomething", 123).Return(true, nil)
  // 我们要测试的函数
  targetFuncThatDoesSomethingWithObj(testObj)
  // 断言符合预期,即 testObj.DoSomething(123) 会被调用
  testObj.AssertExpectations(t)
}

On方法设置预期(expectations)时,传入的参数可以使用 mock.Anything,表示任何值都行。如

  // 设置预期,当调用 DoSomething 时,返回 ture,nil
  testObj.On("DoSomething", mock.Anything).Return(true, nil)

如果有多个 mock 对象需要 AssertExpectations,如

testObj1.AssertExpectations(t)
testObj2.AssertExpectations(t)
testObj3.AssertExpectations(t)

可以使用 mock.AssertExpectations 优化

mock.AssertExpectations(t, testObj1, testObj2, testObj3)

mock.Mock 还有一些很实用的常用断言,如:

  • AssertCalled 断言被调用
  • AssertNotCalled 断言没被调用
  • AssertExpectations 断言 On 和 Return 设置的参数和返回值的方法,有被调用
  • AssertNumberOfCalls 断言调用次数

完整的列表可以查看: pkg.go.dev/github.com/…

suite 包

如果你有别的面向对象语言的经验,用 suite 包写单元测试可能更符合你的习惯。我们可以自定义一个结构体,它依赖 suite.Suite,它所有的以 Test 开头的函数,都是一个测试。

import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/suite"
)
// 依赖 suite.Suite
type ExampleTestSuite struct {
    suite.Suite
    VariableThatShouldStartAtFive int
}
// 每个测试运行前,会执行
func (suite *ExampleTestSuite) SetupTest() {
    suite.VariableThatShouldStartAtFive = 5
}
// 所有以“Test”开头的方法,都是一个测试
func (suite *ExampleTestSuite) TestExample() {
    assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}
// 用于 'go test' 的入口
func TestExampleTestSuite(t *testing.T) {
    suite.Run(t, new(ExampleTestSuite))
}

除了 SetupTest,suite.Suite 还有一些钩子:

TearDownTest 每个测试之后执行

SetupSuite Suite 开始之前执行一次,在所有测试之前执行

TearDownSuite Suite 结束之后执行一次,在所有测试之后执行

更多的介绍可以查看官网:pkg.go.dev/github.com/…

引用

pkg.go.dev/github.com/…

以上就是Go单元测试利器testify使用示例详解的详细内容,更多关于Go 单元测试testify的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go单元测试对数据库CRUD进行Mock测试

    目录 go-sqlmock 安装 使用示例 miniredis 安装 使用示例 总结 最近在实践中也总结了一些如何用表格驱动的方式使用 gock Mock测试外部接口调用.以及怎么对GORM做mock测试,这些等这篇学完基础后,后面再单独写文章给大家介绍. 这是Go语言单元测试系列教程的第3篇,介绍了如何使用go-sqlmock和miniredis工具进行MySQL和Redis的mock测试. 在上一篇<Go单元测试--模拟服务请求和接口返回>中,我们介绍了如何使用httptest和gock工

  • Go语言单元测试基础从入门到放弃

    目录 Go语言测试 go test工具 单元测试函数 格式 单元测试示例 go test -v go test -run 回归测试 跳过某些测试用例 子测试 表格驱动测试 介绍 示例 并行测试 使用工具生成测试代码 测试覆盖率 testify/assert 安装 使用示例 总结 Go语言测试 这是Go单测从入门到放弃系列教程的第0篇,主要讲解在Go语言中如何做单元测试以及介绍了表格驱动测试.回归测试,并且介绍了常用的断言工具. go test工具 Go语言中的测试依赖go test命令.编写测试

  • Golang 单元测试和基准测试实例详解

    目录 前言 Go 单元测试 单元测试覆盖率 基准测试 前言 多人协作的项目里,要保证代码的质量,自然离不开单元测试.开发完一个功能后肯定要对所写的代码进行测试,测试没有问题之后再合并到代码库供他人使用.如果强行合并到代码库可能会影响其他人开发,被上线的话肯定也会导致线上 Bug ,影响用户使用. 所以,单元测试也是一个很重要的事情.单元测试是指在开发中,对一个函数或模块的测试.其强调的是对单元进行测试. Go 单元测试 Go 语言提供了单元测试的框架,只要遵循其规则即可: 测试文件命名: 单元测

  • Go语言单元测试模拟服务请求和接口返回

    目录 前言 httptest gock 安装 使用示例 总结 前言 这是Go单元测试从入门到放弃系列教程的第1篇,介绍了如何使用httptest和gock工具进行网络测试. 在上一篇<Go单元测试从入门到放弃—0.单元测试基础>中,我们介绍了Go语言编写单元测试的基础内容. 而实际工作中的业务场景往往会比较复杂,无论我们的代码是作为server端对外提供服务或者还是我们依赖别人提供的网络服务(调用别人提供的API接口)的场景,我们通常都不想在测试过程中真正的建立网络连接.本文就专门介绍如何在上

  • Go语言测试库testify使用学习

    目录 简介 准备工作 assert Contains DirExists ElementsMatch Empty EqualError EqualValues Error ErrorAs ErrorIs 逆断言 Assertions 对象 require mock suite 测试 HTTP 服务器 总结 简介 testify可以说是最流行的(从 GitHub star 数来看)Go 语言测试库了.testify提供了很多方便的函数帮助我们做assert和错误信息输出.使用标准库testing,

  • Go单元测试对GORM进行Mock测试

    目录 前言 项目准备 初始化测试工作 对Create进行Mock测试 Get 操作的Mock测试 Update 操作的Mock测试 总结 前言 在 Go 单元测试这个系列的第二部分 数据库的Mock测试 中我们介绍了用 go-sqlmock 给数据库的 CRUD 操作做Mock 测试的方法,不过里面只是讲解了一下怎么对原生的database/sql执行的 SQL 进行 Mock 测试. 真实的开发场景下我们的项目一般都会使用 ORM ,而不是原生的database/sql来完成数据库操作.在很多

  • Go语言基础单元测试与性能测试示例详解

    目录 概述 单元测试 代码说明如下 问题 注意 性能测试 基本使用 自定义测试时间 概述 测试不是Go语言独有的,其实在很多语言都有测试,例如:Go.Java.Python- 要想成为一名合格的大牛,这是程序员必须具备的一项技能,特别是一些大公司,这是加分的一项,主要有如下优点: 代码可以随时测试,保证代码不会产生错误 写出更加高效的代码 testing文档 Testing_flags文档 单元测试 格式:func TestXXX(t *testing.T) //add.go package c

  • Go单元测试利器testify使用示例详解

    目录 testify assert 包 require 包 mock 包 suite 包 testify 在团队里推行单元测试的时候,有一个反对的意见是:写单元测试耗时太多.且不论这个意见对错,单元测试确实不应该太费时间.这时候,一个好的单测辅助工具,显得格外重要.本文推荐的 testify(github.com/stretchr/te…) 包,具有断言.mock 等功能,能配合标准库,使你的单元测试更加简洁易读. testify 有三个主要功能: 断言,在 assert 包和 require

  • Go 语言进阶单元测试示例详解

    目录 前言 测试 单元测试 规则 示例 assert 覆盖率 依赖 Mock 基准测试 前言 本文从单元测试实践角度出发,提升对代码质量的意识. 本文内容主要包括:单元测试.Mock测试.基准测试. 测试 测试可以提高代码的质量.减少事故的发生. 测试又分为:回归测试.集成测试.单元测试. 回归测试是指对QA手动回归一些特定场景,可以理解为我们说的手动点点. 集成测试是指对系统功能维度做验证,比如对服务暴露的接口验证,一般是自动化的验证. 单元测试是指在开发阶段,开发者对单独的函数.模块做验证,

  • go并发利器sync.Once使用示例详解

    目录 1. 简介 2. 基本使用 2.1 基本定义 2.2 使用方式 2.3 使用例子 3. 原理 4. 使用注意事项 4.1 不能将sync.Once作为函数局部变量 4.2 不能在once.Do中再次调用once.Do 4.3 需要对传入的函数进行错误处理 4.3.1 基本说明 4.3.2 未错误处理导致的问题 4.3.3 处理方式 5. 总结 1. 简介 本文主要介绍 Go 语言中的 Once 并发原语,包括 Once 的基本使用方法.原理和注意事项,从而对 Once 的使用有基本的了解.

  • C语言实现单元测试的示例详解

    目录 前沿 使用前提 测试框架如下 测试方法编写文件 验证 前沿 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等.总的来说,单元就是人为规定的最小的被测功能模块.单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试. 在网上找了找C语言都没有类似j

  • Golang单元测试与断言编写流程详解

    目录 编写单元测试 批量测试(test tables) 执行测试 性能测试 配置计算时间 断言(assertion) Go 在testing包中内置测试命令go test,提供了最小化但完整的测试体验.标准工具链还包括基准测试和基于代码覆盖的语句,类似于NCover(.NET)或Istanbul(Node.js).本文详细讲解go编写单元测试的过程,包括性能测试及测试工具的使用,另外还介绍第三方断言库的使用. 编写单元测试 go中单元测试与语言中其他特性一样具有独特见解,如格式化.命名规范.语法

  • spring结合hibernate示例详解

    单纯Hibernate程序 1.首先是导入hibernate的jar包. 2. 建立用户和用户操作记录实体,Log.Java和User.java.代码如下所示. Log.java import java.util.Date; public class Log { private int id; //日志的类别.日志一般起到一个不可否认性. //操作日志 安全日志 事件日志. private String type; private String detail; private Date time

  • springboot单元测试两种方法实例详解

    这篇文章主要介绍了springboot单元测试两种方法实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot的单元测试,这里介绍两种方式,一种是在测试类中添加注解:另一种是在代码中启动项目的main方法中继承接口(也可以写在其他方法中). 如 对查看数据库的连接池信息 进行单元测试 1. 在类上使用注解: @RunWith(SpringRunner.class) @SpringBootTest @RunWith(Sprin

  • Flutter 中 Dart的Mixin示例详解

    原文在这里.写的不错,推荐各位看原文. 这里补充一下Mixin的定义: 只要一个类是继承自Object的而且没有定义构造方法,那么这个类可以是一个Mixin了.当然,如果你想让mixin的定义更加的清晰,可以使用mixin关键字开头来定义.具体请参考这里 原文截图体会一下风格. 正文 在经典的面向对象编程语言里一定会有常规的类,抽象类和接口.当然,Dart也有它自己的接口,不过那是另外的文章要说的.有的时候阴影里潜伏者另外的野兽:Mixin!这是做什么的,如何使用?我们来一起发现. 没有mixi

  • Go微服务项目配置文件的定义和读取示例详解

    目录 前言 场景 定义配置 配置文件 加载配置文件 实现原理 总结 项目地址 前言 我们在写应用时,基本都会用到配置文件,从各种 shell 到 nginx 等,都有自己的配置文件.虽然这没有太多难度,但是配置项一般相对比较繁杂,解析.校验也会比较麻烦.本文就给大家讲讲我们是怎么简化配置文件的定义和解析的. 场景 如果我们要写一个 Restful API 的服务,配置项大概有如下内容: Host,侦听的 IP,如果不填,默认用 0.0.0.0 Port,侦听的端口,必填,只能是数字,大于等于80

随机推荐