首页>>后端>>Golang->golang 打桩,mock 数据怎么玩?

golang 打桩,mock 数据怎么玩?

时间:2023-11-30 本站 点击:0

工作中,很多公司都要求效能,要求自动化测试。

实际落地的过程中发现,要做单元测试,自动化测试,可能当前这个服务会依赖其他服务的数据,接口等等。

那么单测或者自动化的过程中,就可能会由于其他服务的原因或者环境因素导致测试失败,或者阻塞测试。

这是一个问题,必须得解决,我们可以采用 golang 自带的 mock 工具来完成,可以在一些必要的地方进行数据打桩,mock 数据。

gomock 是什么?

是官方提供的 一个 mock 数据的 框架

官方还提供了 mockgen 工具用来帮助 我们 生成测试代码

github 上项目地址是:https://github.com/golang/mock

官方是这样介绍 gomock 的:

gomock 是一个用于Go 编程语言的 mocking 框架。它与 Go 的内置测试包集成得很好,但也可以在其他环境中使用。

如何使用 gomock?

使用 gomock 也是非常简单的,先 go get 对应的 工具 gomock 和 mockgen

goget-ugithub.com/golang/mock/gomockgoget-ugithub.com/golang/mock/mockgen

可以写一个 demo 来进行实践

目录结构是这样的

gomock_test├──go.mod├──go.sum├──main.go└──myfunc├──mock_myfunc.go├──myfunc.go├──myuser.go└──myuser_test.go

mock_myfunc.go 是使用 mockgen 工具生成的

myfunc.go 主要是用于模拟调用的底层实现

myuser.go 主要是去调用 myfunc.go 里面的接口

myuser_test.go 是 对应的单测文件

myfunc.go

编写一个 接口,里面有一个 GetInfo() string 方法,模拟获取信息

packagemyfunctypeMyFuncinterface{GetInfo()string}

myuser.go

调用 myfunc.go 中的方法,调用接口获取信息

packagemyfuncfuncgetUser(mMyFunc)string{user:=m.GetInfo()returnuser}

mock 文件的生成

mock_myfunc.go

这个文件不是我们自己写的,是通过 mockgen 工具生成的 ,生成方式如下:

在 myfunc.go 的同级目录下执行如下语句,填入 source 源文件 和 目标文件即可生成新的 mock 文件

mockgen-source=myfunc.go-destination=mock_myfunc.go

我们可以看一下 mockgen 的帮助文档,还有其他的参数供我们使用

#mockgenmockgenhastwomodesofoperation:sourceandreflect.Sourcemodegeneratesmockinterfacesfromasourcefile.Itisenabledbyusingthe-sourceflag.Otherflagsthatmaybeusefulinthismodeare-importsand-aux_files.Example:mockgen-source=foo.go[otheroptions]Reflectmodegeneratesmockinterfacesbybuildingaprogramthatusesreflectiontounderstandinterfaces.Itisenabledbypassingtwonon-flagarguments:animportpath,andacomma-separatedlistofsymbols.Example:mockgendatabase/sql/driverConn,Driver-aux_filesstring(sourcemode)Comma-separatedpkg=pathpairsofauxiliaryGosourcefiles.-build_flagsstring(reflectmode)Additionalflagsforgobuild.-copyright_filestringCopyrightfileusedtoaddcopyrightheader-debug_parserPrintoutparserresultsonly.-destinationstringOutputfile;defaultstostdout.-exec_onlystring(reflectmode)Ifset,executethisreflectionprogram.-importsstring(sourcemode)Comma-separatedname=pathpairsofexplicitimportstouse.-mock_namesstringComma-separatedinterfaceName=mockNamepairsofexplicitmocknamestouse.Mocknamesdefaultto'Mock'+interfaceNamesuffix.-packagestringPackageofthegeneratedcode;defaultstothepackageoftheinputwitha'mock_'prefix.-prog_only(reflectmode)Onlygeneratethereflectionprogram;writeittostdoutandexit.-self_packagestringThefullpackageimportpathforthegeneratedcode.Thepurposeofthisflagistopreventimportcyclesinthegeneratedcodebytryingtoincludeitsownpackage.Thiscanhappenifthemock'spackageissettooneofitsinputs(usuallythemainone)andtheoutputisstdiosomockgencannotdetectthefinaloutputpackage.Settingthisflagwillthentellmockgenwhichimporttoexclude.-sourcestring(sourcemode)InputGosourcefile;enablessourcemode.-versionPrintversion.-write_package_commentWritespackagedocumentationcomment(godoc)iftrue.(defaulttrue)2021/10/3016:43:25Expectedexactlytwoarguments

一般用的比较多的就是

-source 源文件

-destination 目标文件

-imports 依赖的需要 import 的包

-build_flags 传递给build工具的参数

-aux_files 接口文件不止一个文件时附加文件

-package 设置 mock 文件的包名,不设置的话,mock 文件的包名默认是 mock_输入文件的包名

通过上述指令生成的 mock 文件如下:

NewMockMyFunc

创建一个新的 mock 实例

EXPECT

允许调用者指示预期用途的对象

GetInfo

mock 的基础方法,也就是我们需要 mock 的方法

具体的如何使用

myuser_test.go

myuser.go 对应的单测文件 , 使用了 mock 的方式

packagemyfuncimport("fmt""testing"gomock"github.com/golang/mock/gomock")funcTest_getUser(t*testing.T){mockCtl:=gomock.NewController(t)mockMyFunc:=NewMockMyFunc(mockCtl)mockMyFunc.EXPECT().GetInfo().Return("xiaomotong")v:=getUser(mockMyFunc)ifv=="xiaomotong"{fmt.Println("getuserright!")}else{t.Error("geterroruser")}}

看到上述单测文件,可以还不是特别明白区别,我们来看看不用 mock 的时候,我们会是如何去写单测呢

packagemyfuncimport("fmt""testing"gomock"github.com/golang/mock/gomock")funcTest_getUser(t*testing.T){m:=myfunc.CreateMyFunc()//也就是说需要自己创建一个对象v:=getUser(m)ifv=="xiaomotong"{fmt.Println("getuserright!")}else{t.Error("geterroruser")}}

m := myfunc.CreateMyFunc() 看到上述这一句话,是创建对应的对象,再将该对象作为参数传入到 getUser 函数中,正常情况下这样做单测没有问题

但是如果这个时候创建 MyFunc 对象由于对外部还有依赖导致还没有编码好,可是也不能阻塞我们的单元测试

这个时候使用最上面的 mock 方案就显得尤为重要,可以使用 mock 的方式,mock 一个 MyFunc 对象,并设置好返回值即可完成,如:

mockCtl:=gomock.NewController(t)mockMyFunc:=NewMockMyFunc(mockCtl)mockMyFunc.EXPECT().GetInfo().Return("xiaomotong")

执行上述代码结果如下:

>gotestgetuserright!PASSokmygomock/myfunc0.427s

感兴趣的朋友可以使用起来,用的多了就会更加熟悉

使用 gomock 的好处?

gomock 实现了较为完整的基于 interface 的 Mock 功能,能够与 Golang 内置的 testing包良好集成,也能用于其它的测试环境中

学习成本低,很快就能上手

工具需要用起来,才能发挥他的价值,需要的可以用起来吧~

作者:小魔童哪吒


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/4602.html