编写可测试的better go代码示例分析
编写可测试的better go代码示例分析
今天给大家介绍一下编写可测试的better go代码示例分析。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。
在开发一个接口的时候,通常要引入数据库、redis、或者内部调用其他服务,单元测试需要先将对应的数据库、redis、第三方服务都启动,不然,没法做单元测试。 下面就是解决这种情况,原则上认为底层相关服务都已经经过了严格的单元测试,所以将相关的方法提取出来,在单元测试的时候,模拟替换实际的数据库、redis、或其他内部的服务。
一个普通的例子
下面启动了一个http服务,对外提供一个/bad接口,这个接口的功能就是接收一个string类型的参数 args,并通过db查询出apps
//better/main.gopackagemainimport("errors""net/http""better/service""github.com/jinzhu/gorm")funcmain(){http.HandleFunc("/bad",func(whttp.ResponseWriter,r*http.Request){args:=r.URL.Query().Get("args")//initdbdb,err:=dao.NewStorage()iferr!=nil{w.Write([]byte(err.Error()))w.WriteHeader(http.StatusBadRequest)return}apps,err:=service.NewHandle().GetApps(args,db.DB)iferr!=nil{w.Write([]byte(err.Error()))w.WriteHeader(http.StatusBadRequest)return}w.Write([]byte(apps))w.WriteHeader(http.StatusOK)return})err:=http.ListenAndServe(":8080",nil)iferr!=nil{panic(err)}}
service层
//better/service/bad.gopackageserviceimport("errors""github.com/jinzhu/gorm")typehandlestruct{}funcNewHandle()*handle{return&handle{}}func(hhandle)GetApps(argsstring,db*gorm.DB)(appsstring,errerror){ifargs==""{return"",errors.New("argsisnil")}//引入dberr=db.Find(&apps).Erroriferr!=nil{return"",err}returnapps,nil}
数据库层
//better/dao/apps.gopackagedaoimport"github.com/jinzhu/gorm"typeStoragestruct{DB*gorm.DB}funcNewStorage()(*Storage,error){db,err:=gorm.Open("user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local")iferr!=nil{returnnil,err}return&Storage{DB:db},nil}func(s*Storage)GetApps()(string,error){return"daoapps",nil}
单元测试代码
//better/service/bad_test.gopackageserviceimport("testing""github.com/jinzhu/gorm")funcTest_GetApps(t*testing.T){db,err:=gorm.Open("user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local")iferr!=nil{t.Fatal("gormopenerr",err.Error())}_,err=NewHandle().GetApps("test",db)iferr!=nil{t.Fatal("getAppserr",err.Error())}t.Log("success")}
如果要针对func (h handle) getApps(args string, db *gorm.DB) (apps string, err error) 这个方法进行单元测试,我们就不得不启动一个mysql,这样单元测试代码就db严重耦合了。如果方法内部还涉及了调用其他服务,我们还得启动其他服务,这样单元测试写起来就非常不方便。
一种更好的实现方式
新增一个better接口
//better/main.gopackagemainimport("net/http""better/dao""better/service""github.com/jinzhu/gorm")funcmain(){http.HandleFunc("/better",func(whttp.ResponseWriter,r*http.Request){args:=r.URL.Query().Get("args")//initdbdb,err:=dao.NewStorage()iferr!=nil{w.Write([]byte(err.Error()))w.WriteHeader(http.StatusBadRequest)return}apps,err:=service.NewBetterHandle(db).GetApps(args)iferr!=nil{w.Write([]byte(err.Error()))w.WriteHeader(http.StatusBadRequest)return}w.Write([]byte(apps))w.WriteHeader(http.StatusOK)return})err:=http.ListenAndServe(":8080",nil)iferr!=nil{panic(err)}}
service层
//better/service/better.gopackageserviceimport"errors"//bettergotypebetterHandlestruct{StorageBetterHandleStorage}typeBetterHandleStorageinterface{GetApps()(string,error)}funcNewBetterHandle(storageBetterHandleStorage)*betterHandle{return&betterHandle{Storage:storage}}func(hbetterHandle)GetApps(argsstring)(appsstring,errerror){ifargs==""{return"",errors.New("argsisnil")}apps,err=h.Storage.GetApps()iferr!=nil{return"",err}returnapps,nil}
单元测试
packageserviceimport("testing")funcTest_BetterGetApps(t*testing.T){varmDBMockapps,err:=NewBetterHandle(&m).GetApps("Test_BetterGetApps")iferr!=nil{t.Fatal("getAppserr",err.Error())}t.Log("apps:",apps)}typeDBMockstruct{}//构建mock数据//这样我们就可以测试我们的方法,而不需要启动一个dbfunc(m*DBMock)GetApps()(string,error){return"mockapps",nil}
以上就是编写可测试的better go代码示例分析的全部内容了,更多与编写可测试的better go代码示例分析相关的内容可以搜索恰卡编程网之前的文章或者浏览下面的文章进行学习哈!相信小编会给大家增添更多知识,希望大家能够支持一下恰卡编程网!
推荐阅读
-
go如何实现职责链模式
-
Go Callvis如何使用
-
go pprof如何使用
-
Go框架三件套Gorm、Kitex、Hertz怎么使用
-
Go语言单元测试和基准测试实例代码分析
-
go Realize怎么使用
goRealize怎么使用本文小编为大家详细介绍“goReal...
-
14天学会Go语言第四天:Array Map Slice 数组 和切片
-
如何从 PHP 过渡到 Golang?
我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗...
-
零经验Go语言MVC框架,并推荐PHP函数库和MySQL表自动转struct
最近搭建k8s系统,为了调试自动部署用Go做了个MVC框架,这是个适用于喜欢Go语言练习的框架,零Go语言经验学习Go;配合Go模...
-
从php到Golang系统的演变