Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >go测试框架gomock的使用

go测试框架gomock的使用

原创
作者头像
Johns
修改于 2022-06-30 02:26:45
修改于 2022-06-30 02:26:45
4.9K0
举报
文章被收录于专栏:代码工具代码工具

一。介绍

gomock是golang官方开发维护的接口级别的mock方案,包含了GoMock包和mockgen工具两部分,其中GoMock包完成对桩对象生命周期的管理,mockgen工具用来生成interface对应的Mock类源文件。要使用gomock的一个前提是模块之间务必通过接口进行依赖,而不是依赖具体实现,否则mock会非常困难。这个工具目前业界用的并不多,主要是局限性太大,所以我们只需要简单了解一下如何使用就行。

github地址:https://github.com/golang/mock

二。使用

1. 安装

代码语言:txt
AI代码解释
复制
go get -u github.com/golang/mock/gomock
go install github.com/golang/mock/mockgen

2. Quick start

第一步:定义接口,注意这个工具之支持对接口生成mock,其他的类型方法不支持。
代码语言:txt
AI代码解释
复制
package dao

import (
	"fmt"
	_ "github.com/golang/mock/mockgen/model"
)

// 用户持久层操作对象
type UserDao interface {
	Update(id, name, phoneNumber string) int64
	Update2(param ...string) int64
	Add(name, phoneNumber string) (int64, error)
	Select(id string) int64
	Delete(id string) int64
}

type userDao struct{}

func (u userDao) Update(id, name, phoneNumber string) int64 {
	fmt.Println(id, name, phoneNumber)
	return 1
}
第二步:使用命令生成mock类
代码语言:txt
AI代码解释
复制
mockgen  -destination mock_user_dao.go -package dao -source user_dao.go 

如果觉得命令太长了,可以直接在UserDao上面加个go:generate的注释如下

代码语言:txt
AI代码解释
复制
package dao

import (
	"fmt"
	_ "github.com/golang/mock/mockgen/model"
)

//go:generate mockgen -destination mock_user_dao.go -package dao -source user_dao.go
// 用户持久层操作对象
type UserDao interface {
	Update(id, name, phoneNumber string) int64
	Update2(param ...string) int64
	Add(name, phoneNumber string) (int64, error)
	Select(id string) int64
	Delete(id string) int64
}
...

然后在当前包的目录下bash执行go generate也是可以生成mock文件的。

第三步:自定义mock实现并进行断言
代码语言:txt
AI代码解释
复制
package dao

import (
	"errors"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
	"testing"
)

/**
 * @Description
 * @Author guirongguo
 * @Email 
 * @Date 2021/8/31 20:37
 **/

func Test_userDao(t *testing.T) {

	// step1. 初始化一个mock controller
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()
	mockObj := NewMockUserDao(mockCtrl)

	// step2. 定义mock的具体执行逻辑
	// 1.参数支持Eq,Any,Not,Nil
	//Eq(value) 表示与 value 等价的值。
	//Any() 可以用来表示任意的入参。
	//Not(value) 用来表示非 value 以外的值。
	//Nil() 表示 None 值
	//
	// 2.mock方法调用次数支持如下
	//Times() 断言 Mock 方法被调用的次数。
	//MaxTimes() 最大次数。
	//MinTimes() 最小次数。
	//AnyTimes() 任意次数(包括 0 次)
	//
	// 3.返回值支持
	// Return 返回确定的值
	// Do Mock 方法被调用时,要执行的操作吗,忽略返回值。
	// DoAndReturn 可以动态地控制返回值。
	c1 := mockObj.EXPECT().Update("001", "ggr", "10010").Return(int64(1))
	c2 := mockObj.EXPECT().Update("001", "ggr", gomock.Any()).Return(int64(1))
	mockObj.EXPECT().Add("", "1001").Return(int64(0), errors.New("name is invalid")).AnyTimes()
	mockObj.EXPECT().Add("1001", gomock.Not("1001")).Return(int64(0), errors.New("phone_number is invalid")).MinTimes(1)
	mockObj.EXPECT().Add(gomock.Eq("1001"), "1001").Return(int64(0), errors.New("name is empty")).Times(1)
	mockObj.EXPECT().Select(gomock.Any()).Return(int64(1)).MaxTimes(2)
	mockObj.EXPECT().Update2(gomock.Any()).Return(int64(1)).Times(2)

	mockObj.EXPECT().Delete("1001").Do(func(i string) {
		t.Log("delete id=1001")
	})

	mockObj.EXPECT().Delete(gomock.Not("1001")).DoAndReturn(func(i string) int64 {
		return int64(1)
	})

	// step3. 限制stub函数的调用顺序,如果顺序不一致,则报错
	gomock.InOrder(c1, c2)

	// step4. 测试验证
	ret1 := mockObj.Update("001", "ggr", "10010")
	ret2 := mockObj.Update("001", "ggr", "10020")
	ret3 := mockObj.Update2("1", "")
	ret4 := mockObj.Update2("")
	ret5 := mockObj.Select("")
	ret6, err1 := mockObj.Add("1001", "1001")
	ret7, err2 := mockObj.Add("1001", "1002")
	ret8 := mockObj.Delete("1001")
	ret9 := mockObj.Delete("1002")

	// step5. 断言
	assert.Equal(t, ret1, int64(1))
	assert.Equal(t, ret2, int64(1))
	assert.Equal(t, ret3, int64(1))
	assert.Equal(t, ret4, int64(1))
	assert.Equal(t, ret5, int64(1))
	assert.Equal(t, ret6, int64(0))
	assert.Equal(t, ret7, int64(0))
	assert.Equal(t, ret8, int64(0))
	assert.Equal(t, ret9, int64(1))
	assert.NotNil(t, err1)
	assert.NotEmpty(t, err2)
}

自定义mock实现主要包含了自定义参数,自定义返回值,自定义mock调用次数以及调用顺序。

(1)自定义参数

参数支持Eq,Any,Not,Nil,分别代表一下含义:

  • Eq(value) 用于参数为固定值的场景。
  • Any() 用于任意参数的场景。
  • Not(value) 用于表示参数非 value 以外的值场景。
  • Nil() 用于表示参数None 值的场景

(2)自定义返回值

返回值支持如下几种:

  • Return 用于返回确定的值的场景
  • Do 用于无返回值的场景。
  • DoAndReturn 用于可以动态地控制返回值。

(3)自定义mock调用次数

mock调用次数支持如下几种场景:

  • Times() 断言 Mock 方法被调用的次数, 指定次数。
  • MaxTimes() 最大次数。
  • MinTimes() 最小次数。
  • AnyTimes() 任意次数(包括 0 次)

(4)自定义mock调用顺序

当存在多个mock之间相互调用的情况时,可以通过一下2种方式定义mock执行的顺序:

  • 直接在函数后面接After
  • 使用gomock.InOrder设置执行顺序

更多使用方法请参考官方文档:https://pkg.go.dev/github.com/golang/mock/gomock#pkg-examples

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
go test 测试用例那些事(二) mock
关于go的单元测试,之前有写过一篇帖子go test测试用例那些事,但是没有说go官方的库mock,很有必要单独说一下这个库,和他的实现原理。 mock主要的功能是对接口的模拟,需要在写代码的时候定义抽象很多接口,有时为了能方便go test可能会多写一些冗余代码,但这些工作会让你的单元测试更灵活。特别是逻辑比较复杂的时候,上层要调用其他层的方法进行单元测试,会让单元测试越写越麻烦,越写越复杂,这也是很多人不喜欢写单元测试的原因。使用mock模拟底层的接口,能让你只关注上层需要测试的逻辑,而不用为了测试一个功能,写一堆调用的底层的相关的测试逻辑。
lpxxn
2020/07/22
8960
go test 测试用例那些事(二) mock
白话Golang单元测试
最近学习某个 Golang 单元测试的课程,发现其中推荐使用 gomonkey 这种黑科技,让人略感意外,毕竟在软件开发领域,诸如依赖注入之类的概念已经流传了几十年了,本文希望通过一个例子的演化过程,来总结出 Golang 单元测试的最佳实战。
LA0WAN9
2021/12/14
5240
Go Mock 接口测试 单元测试 极简教程
To get the latest released version use: Go version < 1.16
一个会写诗的程序员
2022/05/30
2.1K0
Go Mock 接口测试 单元测试 极简教程
Golang 单元测试 - 逻辑层
前面我们完成了最麻烦的数据层的单元测试,今天我们来看看单元测试中最容易做的一层,数据逻辑层,也就是我们通常说的 service 或者 biz 等,是描述具体业务逻辑的地方,这一层包含我们业务最重要的逻辑。
LinkinStar
2023/02/22
5500
Go每日一库之91:gomock
testing包里 介绍了 Go 语言中单元测试的常用方法,包括子测试(subtests)、表格驱动测试(table-driven tests)、帮助函数(helpers)、网络测试和基准测试(Benchmark)等。这篇文章介绍一种新的测试方法,mock/stub 测试,当待测试的函数/对象的依赖关系很复杂,并且有些依赖不能直接创建,例如数据库连接、文件I/O等。这种场景就非常适合使用 mock/stub 测试。简单来说,就是用 mock 对象模拟依赖项的行为。
luckpunk
2023/09/30
5190
golang单元测试之mock
前面介绍了golang的一般单元测试,以及如何使用vscode进行高效的go单元测试开发。同时也说过一般单元测试重点在于cpu和内存类型的测试,而对io类型的测试是比较敏感的。那么针对这类测试就没法做单元测试了吗?有的,肯定是有的,这就是mock技术。
黑光技术
2019/03/06
11.6K0
golang单元测试之mock
手把手教你如何进行 Golang 单元测试
点击上方蓝字,发现更多精彩 导语 本篇是对单元测试的一个总结,通过完整的单元测试手把手教学,能够让刚接触单元测试的开发者从整体上了解一个单元测试编写的全过程。最终通过两个问题,也能让写过单元测试的开发者收获单测执行时的一些底层细节知识。 引入 随着工程化开发在司内大力的推广,单元测试越来越受到广大开发者的重视。在学习的过程中,发现网上针对 Golang 单元测试大多从理论角度出发介绍,缺乏完整的实例说明,晦涩难懂的 API 让初学接触者难以下手。 本篇不准备大而全的谈论单元测试、笼统的介绍 Golang
腾讯VTeam技术团队
2021/06/02
1.6K0
Go:微服务架构下的单元测试(基于 Ginkgo、gomock 、Gomega)
本文主要使用 Ginkgo[2] 、gomock[3] 、Gomega[4] 工具来实现单元测试,之前不了解的同学,可以先熟悉一下相关文档。
Freedom123
2024/03/29
6610
Go:微服务架构下的单元测试(基于 Ginkgo、gomock 、Gomega)
Go单测系列4—mock接口测试
这是Go语言单元测试从零到溜系列教程的第3篇,介绍了如何在单元测试中使用gomock和gostub工具mock接口和打桩。
luckpunk
2023/09/10
7660
Go 单元测试之mock接口测试
gomock 是一个 Go 语言的测试框架,在实际项目中,需要进行单元测试的时候。却往往发现有一大堆依赖项。这时候就是 Gomock 大显身手的时候了,用于编写单元测试时模拟和测试依赖于外部服务的代码。它允许你创建模拟对象(Mock Objects),这些对象可以预设期望的行为,以便在测试时模拟外部依赖,通常使用它对代码中的那些接口类型进行mock。
贾维斯Echo
2024/04/19
2820
Go 单元测试之mock接口测试
Golang 单元测试详尽指引
文末有彩蛋。 作者:yukkizhang,腾讯 CSIG 专项技术测试工程师 本篇文章站在测试的角度,旨在给行业平台乃至其他团队的开发同学,进行一定程度的单元测试指引,让其能够快速的明确单元测试的方式方法。 本文主要从单元测试出发,对Golang的单元测试框架、Stub/Mock框架进行简单的介绍和选型推荐,列举出几种针对于Mock场景的最佳实践,并以具体代码示例进行说明。 一、单元测试 1. 单元测试是什么 单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向
腾讯技术工程官方号
2020/10/26
4.7K0
go 单元测试进阶篇
腾讯云数据库团队
2017/01/05
9K2
go 单元测试进阶篇
gomock 源码分析
在分析完gostub的源码实现后https://mp.weixin.qq.com/s/I6urCBHbcfZCNaWw1iZmnA,我们分析下gomock的源码实现。两者原理相似,但是也有不同。
golangLeetcode
2022/08/02
3950
使用 Gomock 进行单元测试
在实际项目中,需要进行单元测试的时候。却往往发现有一大堆依赖项。这时候就是 Gomock 大显身手的时候了
李海彬
2018/12/24
3.7K0
一文说尽Golang单元测试实战的那些事儿
导语 | 单元测试,通常是单独测试一个方法、类或函数,让开发者确信自己的代码在按预期运行,为确保代码可以测试且测试易于维护。腾讯后台开发工程师张力结合了公司级漏洞扫描系统洞犀在DevOps上探索的经验,以Golang为例,列举了编写单元测试需要的工具和方法,然后针对写单测遇到的各种依赖问题,详细介绍了通过Mock的方式解决各种常用依赖,方便读者在写go语言UT的时候,遇到依赖问题,能够快速找到解决方案。最后再和大家探讨一下关于单元测试上的一些思考。 一、前言 单元测试,通常是单独测试一个方法、类或函数
腾讯云开发者
2021/07/28
1.5K0
Golang 单元测试合集整理,(我最常用 gomonkey)欢迎收藏
无论写什么样的语言,单元测试都是必不可少的,它可以极大的提高我们的代码质量,减少各种低级错误和 bug
阿兵云原生
2023/09/14
2.1K0
Golang 单元测试合集整理,(我最常用 gomonkey)欢迎收藏
Golang 高质量单元测试之 Table-Driven:从入门到真香
‍ ‍作者:雷畅,腾讯云监控高级工程师 作为一个程序猿 如何在不受外力(领导?)的胁迫下 自觉自愿写单测? 那必然是相信收益 > 成本 单测节省未来修 bug 的时间 > 写单测所花费的时间 为了保证上述不等式成立,强烈建议您考虑 table-driven 方法!table-driven 方法!!table-driven 方法!!!(只说三遍了) 使用 Table-driven 可以快速、无痛写出高质量单测,以降低“我要写单测”这事的心理门槛,最终达到信手拈来、一直写一直爽的神奇效果!(亲测可信) 什么是
腾讯云可观测平台
2022/01/21
1.2K0
go测试框架gomonkey的使用
gomonkey 是 golang 的一款打桩框架,目标是让用户在单元测试中低成本的完成打桩,从而将精力聚焦于业务功能的开发。
Johns
2021/09/03
20.3K0
go test 下篇
go test 上篇 给大家介绍了golang自带的测试框架,包括单元测试和性能测试。但是在实际生产中测试经常会遇到一些网络或者依赖的第三方系统接口,运行测试用例的时候希望忽略这些接口的实际依赖,聚焦在具体业务逻辑代码,这就需要模拟这些接口的行为,也就是我今天介绍给大家的golang/mock,一个golang的mock框架。
用户2937493
2019/09/10
5490
Go项目实战--数据Dao层代码的单元测试实战
上节课我给大家介绍了怎么给Go项目做单元测试的规划,当然这里仅限于跟咱们课程里的实战项目一样分层架构设计做的还可以的项目哦,要是所有逻辑都耦合在Controller里,那这个规划就不适用了。。。,所有逻辑都耦合在Controller里还做个锤子的单元测试,直接上线让用户给你测(手机系统都能这么干的。。。你们怕啥)
KevinYan
2025/04/23
1380
Go项目实战--数据Dao层代码的单元测试实战
相关推荐
go test 测试用例那些事(二) mock
更多 >
交个朋友
加入腾讯云技术交流站
洞悉AI新动向 Get大咖技术交流群
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档