侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

golang分层测试之http接口测试入门教程

Go  /  管理员 发布于 7年前   232

前言

前几话主要讲解关于使用golang进行单元测试,在单元测试的上一层就是接口测试,本节主要讲使用golang进行接口测试,其中主要以http协议的接口测试来讲解

golang中的http请求

golang中拥有一个原生的http依赖库:net/http,http服务器的建立还是http客户端的开发,都会使用到这个依赖库,这里主要讲解时client部分,作为请求发起方应用于日常的接口测试,例示代码如下:

get请求

package mainimport ( "fmt" "io/ioutil" "net/http")func main() { //模拟一个get提交请求 resp, err := http.Get("http://127.0.0.1:12345/checkon") if err != nil {  panic(err) } defer resp.Body.Close() //关闭连接 body, err := ioutil.ReadAll(resp.Body) //读取body的内容 fmt.Println(string(body))}

返回结果

E:\go_project>go run testget.go{ "code": 200, "data": "", "msg": "online", "state": "success"}

post请求:

package mainimport ( "fmt" "io/ioutil" "net/http" "strings")func main() { //模拟一个post提交请求 resp, err := http.Post("http://www.baidu.com", "application/x-www-form-urlencoded", strings.NewReader("id=1")) if err != nil {  panic(err) } //关闭连接 defer resp.Body.Close() //读取报文中所有内容 body, err := ioutil.ReadAll(resp.Body) //输出内容 fmt.Println(string(body))}

上面的post请求以form的方式,最后会返回一个页面

这里说明一下以下这行代码

defer resp.Body.Close()

首先是defer, Go的defer语句用来调度一个函数调用(被延期的函数),使其在执行defer的函数即将返回之前才被运行,被延期执行的函数,它的参数(包括接受者)实在defer执行的时候被求值的,而不是在调用执行的时候。也就是说被延期执行的函数的参数是按正常顺序被求值的,简单理解为,无论defer对应的代码行放在代码段的哪个位置,defer是在return前执行的代码行,但defer代码行中的参数是需要先声明再调用的,对应响应中的处理,golang的Response.Body需要被关闭的,body实际上是一个嵌套了多层的net.TCPConn:

  • bufio.Reader,这层尝试将多次小的读操作替换为一次大的读操作,减少系统调用的次数,提高性能;
  • io.LimitedReader,tcp连接在读取完body后不会关闭,继续读会导致阻塞,所以需要LimitedReader在body读完后发出eof终止读取;
  • chunkedReader,解析chunked格式编码(如果不是chunked略过);
  • bodyEOFSignal,在读到eof,或者是提前关闭body时会对readLoop发出回收连接的通知;
  • gzipReader,解析gzip压缩(如果不是gizp压缩略过);

从上面可以看出如果body既没有被完全读取,也没有被关闭,那么这次http事务就没有完成,除非连接因超时终止了,否则相关资源无法被回收,所以需要我们进行关闭连接的操作,这个是很多golang新手会忽略的一个点,作为client端处理response的时候,body一定要close,否则会造成GC回收不到,继而产生内存泄露

带json的post请求

我们大部分应用到的restful接口都是用json格式的请求体,对应的golang的http请求也会有相关的方式post json请求体

package mainimport ( "fmt" "io/ioutil" "net/http"  "bytes" "encoding/json")type HttpData struct { Flag int `json:"flag"` Msg string `json:"msg"`}func main() { url := "http://127.0.0.1:12345/postdata" contentType := "application/json;charset=utf-8" var httpdata HttpData httpdata.Flag = 1 httpdata.Msg = "terrychow"  b ,err := json.Marshal(httpdata) if err != nil {  fmt.Println("json format error:", err)  return } body := bytes.NewBuffer(b) resp, err := http.Post(url, contentType, body) if err != nil {  fmt.Println("Post failed:", err)  return } defer resp.Body.Close() content, err := ioutil.ReadAll(resp.Body) if err != nil {  fmt.Println("Read failed:", err)  return } fmt.Println("header:", resp.Header) fmt.Println("content:", string(content))}

执行结果响应

E:\go_project>go run gohttptest.goheader: map[Content-Type:[application/json] Content-Length:[78] Server:[Werkzeug/0.14.1 Python/2.7.15] Date:[Thu, 06 Dec 2018 16:35:11 GMT]]content: { "code": 200, "data": 1, "msg": "terrychow", "state": "success"}

对于常用的get和post请求基本上就以照上面的版本执行,当然我们现在需要做的是http接口的测试,那就需要引入测试框架进行相关的校验,本文先讲解用之前提到的gocheck来进行断言

golang中的http接口测试

引入gocheck之后我们得到了以下的脚本:

package hello_testimport ( "testing" "fmt" "strconv" "io/ioutil" "net/http"  "bytes" "encoding/json" . "gopkg.in/check.v1")var a int =1// Hook up gocheck into the "go test" runner.func Test(t *testing.T) { TestingT(t) }type MySuite struct{}type HttpData struct { Flag int `json:"flag"` Msg string `json:"msg"`}var _ = Suite(&MySuite{})var testurl string ="http://127.0.0.1:12345"func (s *MySuite) SetUpSuite(c *C) { str3:="第1次套件开始执行" fmt.Println(str3) //c.Skip("Skip TestSutie")}func (s *MySuite) TearDownSuite(c *C) { str4:="第1次套件执行完成" fmt.Println(str4)}func (s *MySuite) SetUpTest(c *C) { str1:="第"+strconv.Itoa(a)+"条用例开始执行" fmt.Println(str1)}func (s *MySuite) TearDownTest(c *C) { str2:="第"+strconv.Itoa(a)+"条用例执行完成" fmt.Println(str2) a=a+1}func (s *MySuite) TestHttpGet(c *C) { geturl := fmt.Sprintf("%v/checkon", testurl) respget, err := http.Get(geturl) if err != nil {  panic(err) } defer respget.Body.Close() //关闭连接 body, err := ioutil.ReadAll(respget.Body) //读取body的内容 var gdat map[string]interface{} //定义map用于解析resp.body的内容 if err := json.Unmarshal([]byte(string(body)), &gdat); err == nil {  fmt.Println(gdat) } else {  fmt.Println(err) } var gmsg=gdat["msg"] c.Assert(gmsg, Equals, "terrychow") //模拟失败的断言}func (s *MySuite) TestHttpPost(c *C) { url := fmt.Sprintf("%v/postdata", testurl) contentType := "application/json;charset=utf-8" var httpdata HttpData httpdata.Flag = 1 httpdata.Msg = "terrychow"  b ,err := json.Marshal(httpdata) if err != nil {  fmt.Println("json format error:", err)  return } body := bytes.NewBuffer(b) resp, err := http.Post(url, contentType, body) if err != nil {  fmt.Println("Post failed:", err)  return } defer resp.Body.Close() content, err := ioutil.ReadAll(resp.Body) if err != nil {  fmt.Println("Read failed:", err)  return } var dat map[string]interface{} //定义map用于解析resp.body的内容 if err := json.Unmarshal([]byte(string(content)), &dat); err == nil {  fmt.Println(dat) } else {  fmt.Println(err) } var msg=dat["msg"] c.Assert(msg, Equals, "terrychow") //模拟成功的断言}

最后的输出内容:

E:\go_project>go test -v gocheckhttp_test.go=== RUN Test第1次套件开始执行第1条用例开始执行map[code:200 data: msg:online state:success]第1条用例执行完成----------------------------------------------------------------------FAIL: gocheckhttp_test.go:56: MySuite.TestHttpGetgocheckhttp_test.go:72: c.Assert(gmsg, Equals, "terrychow")... obtained string = "online"... expected string = "terrychow"第2条用例开始执行map[msg:terrychow state:success code:200 data:1]第2条用例执行完成第1次套件执行完成OOPS: 1 passed, 1 FAILED--- FAIL: Test (0.02s)FAILFAIL command-line-arguments 0.613s

输出的结果符合预期,这也是比较基本的http接口测试

小结

就上文来说,我们基本可以通过本文掌握如何做http接口测试,其核心还是使用http依赖库发出请求获取响应,利用gocheck进行断言,当然还可以用testing,下一节继续讲一下http接口测试,但会重点讲专门做http接口测试的测试框架httpexpect以及用于mock的httptest,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    Golang学习笔记之延迟函数(defer)的使用小结
    下一条:
    golang如何使用struct的tag属性的详细介绍
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-09
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-12
    • 2021-01
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-08
    • 2024-11
    • 2025-02
    • 2025-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客