欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang分層測試之http接口測試入門教程

 更新時間:2018年12月07日 09:42:08   作者:周學(xué)習(xí)的名字被占了  
這篇文章主要介紹了golang分層測試之http接口測試入門教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

前幾話主要講解關(guān)于使用golang進行單元測試,在單元測試的上一層就是接口測試,本節(jié)主要講使用golang進行接口測試,其中主要以http協(xié)議的接口測試來講解

golang中的http請求

golang中擁有一個原生的http依賴庫:net/http,http服務(wù)器的建立還是http客戶端的開發(fā),都會使用到這個依賴庫,這里主要講解時client部分,作為請求發(fā)起方應(yīng)用于日常的接口測試,例示代碼如下:

get請求

package main

import (
 "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() //關(guān)閉連接
 body, err := ioutil.ReadAll(resp.Body) //讀取body的內(nèi)容
 fmt.Println(string(body))
}

返回結(jié)果

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

post請求:

package main

import (
 "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)
 }
 //關(guān)閉連接
 defer resp.Body.Close()
 //讀取報文中所有內(nèi)容
 body, err := ioutil.ReadAll(resp.Body)
 //輸出內(nèi)容
 fmt.Println(string(body))
}

上面的post請求以form的方式,最后會返回一個頁面

這里說明一下以下這行代碼

defer resp.Body.Close()

首先是defer, Go的defer語句用來調(diào)度一個函數(shù)調(diào)用(被延期的函數(shù)),使其在執(zhí)行defer的函數(shù)即將返回之前才被運行,被延期執(zhí)行的函數(shù),它的參數(shù)(包括接受者)實在defer執(zhí)行的時候被求值的,而不是在調(diào)用執(zhí)行的時候。也就是說被延期執(zhí)行的函數(shù)的參數(shù)是按正常順序被求值的,簡單理解為,無論defer對應(yīng)的代碼行放在代碼段的哪個位置,defer是在return前執(zhí)行的代碼行,但defer代碼行中的參數(shù)是需要先聲明再調(diào)用的,對應(yīng)響應(yīng)中的處理,golang的Response.Body需要被關(guān)閉的,body實際上是一個嵌套了多層的net.TCPConn:

  • bufio.Reader,這層嘗試將多次小的讀操作替換為一次大的讀操作,減少系統(tǒng)調(diào)用的次數(shù),提高性能;
  • io.LimitedReader,tcp連接在讀取完body后不會關(guān)閉,繼續(xù)讀會導(dǎo)致阻塞,所以需要LimitedReader在body讀完后發(fā)出eof終止讀取;
  • chunkedReader,解析chunked格式編碼(如果不是chunked略過);
  • bodyEOFSignal,在讀到eof,或者是提前關(guān)閉body時會對readLoop發(fā)出回收連接的通知;
  • gzipReader,解析gzip壓縮(如果不是gizp壓縮略過);

從上面可以看出如果body既沒有被完全讀取,也沒有被關(guān)閉,那么這次http事務(wù)就沒有完成,除非連接因超時終止了,否則相關(guān)資源無法被回收,所以需要我們進行關(guān)閉連接的操作,這個是很多golang新手會忽略的一個點,作為client端處理response的時候,body一定要close,否則會造成GC回收不到,繼而產(chǎn)生內(nèi)存泄露

帶json的post請求

我們大部分應(yīng)用到的restful接口都是用json格式的請求體,對應(yīng)的golang的http請求也會有相關(guān)的方式post json請求體

package main

import (
 "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))

}

執(zhí)行結(jié)果響應(yīng)

E:\go_project>go run gohttptest.go
header: 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請求基本上就以照上面的版本執(zhí)行,當(dāng)然我們現(xiàn)在需要做的是http接口的測試,那就需要引入測試框架進行相關(guān)的校驗,本文先講解用之前提到的gocheck來進行斷言

golang中的http接口測試

引入gocheck之后我們得到了以下的腳本:

package hello_test

import (
 "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次套件開始執(zhí)行"
 fmt.Println(str3)
 //c.Skip("Skip TestSutie")
}

func (s *MySuite) TearDownSuite(c *C) {
 str4:="第1次套件執(zhí)行完成"
 fmt.Println(str4)
}

func (s *MySuite) SetUpTest(c *C) {
 str1:="第"+strconv.Itoa(a)+"條用例開始執(zhí)行"
 fmt.Println(str1)

}

func (s *MySuite) TearDownTest(c *C) {
 str2:="第"+strconv.Itoa(a)+"條用例執(zhí)行完成"
 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() //關(guān)閉連接

 body, err := ioutil.ReadAll(respget.Body) //讀取body的內(nèi)容
 var gdat map[string]interface{} //定義map用于解析resp.body的內(nèi)容
 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的內(nèi)容
 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") //模擬成功的斷言
}

最后的輸出內(nèi)容:

E:\go_project>go test -v gocheckhttp_test.go
=== RUN Test
第1次套件開始執(zhí)行
第1條用例開始執(zhí)行
map[code:200 data: msg:online state:success]
第1條用例執(zhí)行完成

----------------------------------------------------------------------
FAIL: gocheckhttp_test.go:56: MySuite.TestHttpGet

gocheckhttp_test.go:72:
 c.Assert(gmsg, Equals, "terrychow")
... obtained string = "online"
... expected string = "terrychow"

第2條用例開始執(zhí)行
map[msg:terrychow state:success code:200 data:1]
第2條用例執(zhí)行完成
第1次套件執(zhí)行完成
OOPS: 1 passed, 1 FAILED
--- FAIL: Test (0.02s)
FAIL
FAIL command-line-arguments 0.613s

輸出的結(jié)果符合預(yù)期,這也是比較基本的http接口測試

小結(jié)

就上文來說,我們基本可以通過本文掌握如何做http接口測試,其核心還是使用http依賴庫發(fā)出請求獲取響應(yīng),利用gocheck進行斷言,當(dāng)然還可以用testing,下一節(jié)繼續(xù)講一下http接口測試,但會重點講專門做http接口測試的測試框架httpexpect以及用于mock的httptest,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • golang struct 實現(xiàn) interface的方法

    golang struct 實現(xiàn) interface的方法

    這篇文章主要介紹了golang struct 實現(xiàn) interface的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Go語言項目中使用Viper獲取配置信息詳解

    Go語言項目中使用Viper獲取配置信息詳解

    Viper是Go應(yīng)用的完整配置解決方案,它能處理所有類型的配置需求和配置格式,這篇文章主要介紹了Go項目中使用Viper獲取配置信息,需要的可以參考下
    2024-04-04
  • go設(shè)置多個GOPATH的方式

    go設(shè)置多個GOPATH的方式

    這篇文章主要介紹了go設(shè)置多個GOPATH的方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 如何用go-zero 實現(xiàn)中臺系統(tǒng)

    如何用go-zero 實現(xiàn)中臺系統(tǒng)

    這篇文章主要介紹了如何用go-zero 實現(xiàn)中臺系統(tǒng),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Go 語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表學(xué)習(xí)教程

    Go 語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表學(xué)習(xí)教程

    這篇文章主要為大家介紹了Go 語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表學(xué)習(xí)教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 利用go語言判斷是否是完全二叉樹

    利用go語言判斷是否是完全二叉樹

    這篇文章主要介紹了利用go語言判斷是否是完全二叉樹,當(dāng)一個節(jié)點存在右子節(jié)點但是不存在左子節(jié)點這顆樹視為非完全二叉樹,通過利用GO語言判斷來判斷出否是完全二叉樹,詳細(xì)內(nèi)容參考如下
    2022-05-05
  • Golang 內(nèi)存管理簡單技巧詳解

    Golang 內(nèi)存管理簡單技巧詳解

    這篇文章主要為大家介紹了Golang 內(nèi)存管理簡單技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • golang中接口對象的轉(zhuǎn)型兩種方式

    golang中接口對象的轉(zhuǎn)型兩種方式

    這篇文章主要介紹了golang中接口對象的轉(zhuǎn)型方式,大家都知道接口對象的轉(zhuǎn)型有兩種方式,文中通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • Go語言中零拷貝的原理與實現(xiàn)詳解

    Go語言中零拷貝的原理與實現(xiàn)詳解

    零拷貝是相對于用戶態(tài)來講的,即數(shù)據(jù)在用戶態(tài)不發(fā)生任何拷貝,那么零拷貝的原理是什么,又是如何實現(xiàn)的呢,下面小編就來和大家詳細(xì)聊聊吧
    2023-08-08
  • Go語言map實現(xiàn)順序讀取

    Go語言map實現(xiàn)順序讀取

    當(dāng)我們遍歷 map 時,那就是輸出的鍵值對順序是不確定的,本文主要介紹了Go語言map實現(xiàn)順序讀取, 文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05

最新評論