最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang httptest包測試使用教程

 更新時間:2023年03月15日 10:39:05   作者:夢想畫家  
這篇文章主要介紹了Golang httptest包測試使用,httptest包的理念是,非常容易模擬http服務(wù),也就是說模擬響應(yīng)寫(response writer),提供給http處理器(handle),讓我們測試http服務(wù)端和客戶端很容易

當(dāng)前首次學(xué)習(xí)到Golang httptest包時,著實打動了我。其他語言測試HTTP服務(wù)需要做很多工作或引用第三方工具,讓人不可思議的是,Golang標(biāo)準(zhǔn)庫就提供了非常容易理解的測試包。本文介紹httptest包的使用,為你Go http服務(wù)構(gòu)建更好的端到端的測試。

httptest包的理念是,非常容易模擬http服務(wù),也就是說模擬響應(yīng)寫(response writer),提供給http處理器(handle),讓我們測試http服務(wù)端和客戶端很容易。

本文主要介紹兩個使用httptest的特定場景: 測試http server處理器,測試http客戶端。

測試http服務(wù)端處理器

下面通過示例介紹http server的測試。首先看http服務(wù)程序,把請求字符串轉(zhuǎn)為大寫:

package main
import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "strings"
)
// Req: http://localhost:1234/upper?word=abc
// Res: ABC
func upperCaseHandler(w http.ResponseWriter, r *http.Request) {
    query, err := url.ParseQuery(r.URL.RawQuery)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "invalid request")
        return
    }
    word := query.Get("word")
    if len(word) == 0 {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "missing word")
        return
    }
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, strings.ToUpper(word))
}
func main() {
    http.HandleFunc("/upper", upperCaseHandler)
    log.Fatal(http.ListenAndServe(":1234", nil))
}

現(xiàn)在想測試http server使用的upperCaseHandler邏輯,我們需要準(zhǔn)備兩方面:

  • 使用httptest.NewRequest暴露的函數(shù)創(chuàng)建http.Request對象,NewRequest返回Request, 可以傳給http.Handler進行測試.
  • 使用httptest.NewRecorder函數(shù)創(chuàng)建http.ResponseWriter,返回httptest.ResponseRecorder。ResponseRecorder是

http.ResponseWriter 的實現(xiàn),它記錄變化為了后面測試檢查.

httptest.ResponseRecorder

httptest.ResponseRecorder是 http.ResponseWriter 的實現(xiàn),可以傳給http server handle,記錄所有處理并寫回響應(yīng)的數(shù)據(jù),下面測試程序可以看到其如何實現(xiàn):

package main
import (
    "io/ioutil"
    "net/http"
    "net/http/httptest"
    "testing"
)
func TestUpperCaseHandler(t *testing.T) {
    req := httptest.NewRequest(http.MethodGet, "/upper?word=abc", nil)
    w := httptest.NewRecorder()
    upperCaseHandler(w, req)
    res := w.Result()
    defer res.Body.Close()
    data, err := ioutil.ReadAll(res.Body)
    if err != nil {
        t.Errorf("expected error to be nil got %v", err)
    }
    if string(data) != "ABC" {
        t.Errorf("expected ABC got %v", string(data))
    }
}

上面示例中首先定義請求和響應(yīng),然后傳入處理器進行測試。然后檢查ResponseRecorder的Result方法輸出:

func (rw *ResponseRecorder) Result() *http.Response

Result返回處理器生成的響應(yīng)。返回相應(yīng)至少有StatusCode, Header, Body, 以及可選其他內(nèi)容,未來可能會填充更多字段,所以調(diào)用者在測試中不應(yīng)該深度比較相等。

測試HTTP客戶端

測試服務(wù)端處理器相對容易,特別當(dāng)測試處理器邏輯時,僅需要在測試中模擬http.ResponseWriter 和 http.Request對象。對于HTTP客戶端測試,情況稍晚有點復(fù)雜。原因是有時不容易模擬或復(fù)制整個HTTP Server,請看下面示例:

package main
import (
    "io/ioutil"
    "net/http"
    "github.com/pkg/errors"
)
type Client struct {
    url string
}
func NewClient(url string) Client {
    return Client{url}
}
func (c Client) UpperCase(word string) (string, error) {
    res, err := http.Get(c.url + "/upper?word=" + word)
    if err != nil {
        return "", errors.Wrap(err, "unable to complete Get request")
    }
    defer res.Body.Close()
    out, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return "", errors.Wrap(err, "unable to read response data")
    }
    return string(out), nil
}

client需要url,表示遠程服務(wù)端基地址。然后調(diào)用/upper,帶上輸入單詞,最后返回結(jié)果字符串給調(diào)用者,如果調(diào)用不成功還返回錯誤對象。為了測試這段代碼,需要模擬整個http服務(wù)端邏輯,或至少是響應(yīng)請求路徑:/upper。使用httptest包可以模擬整個http 服務(wù),通過初始化本地服務(wù),監(jiān)聽回環(huán)地址并返回你想要的任何內(nèi)容。

使用 httptest.Server

通過調(diào)用httptest.NewServer函數(shù)生成我們想要的 httptest.Server。表示http服務(wù),監(jiān)聽回環(huán)地址及可選的端口號,用于實現(xiàn)端到端HTTP測試。

func NewServer(handler http.Handler) *Server

NewServer 啟動并返回新的HTTP服務(wù),調(diào)用者使用完成后應(yīng)該調(diào)用Close方法結(jié)束服務(wù)。下面通過示例進行解釋:

package main
import (
    "fmt"
    "net/http"
    "net/http/httptest"
    "strings"
    "testing"
)
func TestClientUpperCase(t *testing.T) {
    expected := "dummy data"
    svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, expected)
    }))
    defer svr.Close()
    c := NewClient(svr.URL)
    res, err := c.UpperCase("anything")
    if err != nil {
        t.Errorf("expected err to be nil got %v", err)
    }
    // res: expected\r\n
    // due to the http protocol cleanup response
    res = strings.TrimSpace(res)
    if res != expected {
        t.Errorf("expected res to be %s got %s", expected, res)
    }
}

上面示例中使用httptest.NewServer函數(shù)創(chuàng)建了模擬http服務(wù)器,給它傳入自定義模擬處理器,總是返回相同的數(shù)據(jù)。并使用服務(wù)端url作為客戶端請求url,從而模擬并讓服務(wù)端返回任何我們想測試的內(nèi)容。

當(dāng)然我們可以修改處理器,讓其返回我們期望的邏輯:

func TestClientUpperCase(t *testing.T) {
	svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		query, err := url.ParseQuery(r.URL.RawQuery)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, "invalid request")
			return
		}
		word := query.Get("word")
		if len(word) > 0 {
			fmt.Fprintf(w, strings.ToUpper(word))
		} else {
			fmt.Fprintf(w, "no input")
		}
	}))
	defer svr.Close()
	expected := "ANYTHING"
	c := NewClient(svr.URL)
	res, err := c.UpperCase("anything")
	if err != nil {
		t.Errorf("expected err to be nil got %v", err)
	}
	// res: expected\r\n
	// due to the http protocol cleanup response
	res = strings.TrimSpace(res)
	if res != expected {
		t.Errorf("expected res to be %s got %s", expected, res)
	}
}

總結(jié)

本文介紹httptest包,可以很方便測試http服務(wù)端處理邏輯,以及模擬http服務(wù)端測試客戶端請求邏輯。由于很方面模擬,從而可以把一組參數(shù)和期望值進行組合,循環(huán)進行測試并對比結(jié)果,可以極大地提升測試效率。

到此這篇關(guān)于Golang httptest包測試使用教程的文章就介紹到這了,更多相關(guān)Go httptest內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang實現(xiàn)的文件上傳下載小工具

    golang實現(xiàn)的文件上傳下載小工具

    這篇文章主要介紹了golang實現(xiàn)的文件上傳下載小工具,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-12-12
  • 詳解go語言中并發(fā)安全和鎖問題

    詳解go語言中并發(fā)安全和鎖問題

    這篇文章主要介紹了go語言中并發(fā)安全和鎖問題,包含互斥鎖解鎖過程,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • go語言中l(wèi)inkname的用法

    go語言中l(wèi)inkname的用法

    這篇文章主要介紹了go語言中l(wèi)inkname的用法,本文給點俺家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Golang通脈之方法詳情

    Golang通脈之方法詳情

    這篇文章主要介紹了Golang通脈方法,Go語言中的方法(Method)是一種作用于特定類型變量的函數(shù)。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于,其他語言中的this或者 self,具體內(nèi)容請和小編一起來學(xué)習(xí)下面文章內(nèi)容吧
    2021-10-10
  • 淺析Go匯編語法和MatrixOne使用介紹

    淺析Go匯編語法和MatrixOne使用介紹

    MatrixOne由Go語言所開發(fā)是一個新一代超融合異構(gòu)數(shù)據(jù)庫,致力于打造單一架構(gòu)處理TP、AP、流計算等多種負載的極簡大數(shù)據(jù)引擎,今天通過本文給大家介紹Go匯編語法和MatrixOne使用,感興趣的朋友一起看看吧
    2022-04-04
  • Go語言深度拷貝工具deepcopy的使用教程

    Go語言深度拷貝工具deepcopy的使用教程

    今天給大家推薦的工具是deepcopy,一個可以對指針、接口、切片、結(jié)構(gòu)體、Map都能進行深拷貝的工具,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2022-09-09
  • Go在GoLand中引用github.com中的第三方包具體步驟

    Go在GoLand中引用github.com中的第三方包具體步驟

    這篇文章主要給大家介紹了關(guān)于Go在GoLand中引用github.com中第三方包的具體步驟,文中通過圖文介紹的非常詳細,對大家學(xué)習(xí)或者使用Go具有一定的參考價值,需要的朋友可以參考下
    2024-01-01
  • Go并發(fā)與鎖的兩種方式該如何提效詳解

    Go并發(fā)與鎖的兩種方式該如何提效詳解

    如果沒有鎖,在我們的項目中,可能會存在多個goroutine同時操作一個資源(臨界區(qū)),這種情況會發(fā)生競態(tài)問題(數(shù)據(jù)競態(tài)),下面這篇文章主要給大家介紹了關(guān)于Go并發(fā)與鎖的兩種方式該如何提效的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • Go json反序列化“null“的問題解決

    Go json反序列化“null“的問題解決

    本文主要介紹了Go json反序列化“null“的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • go語言匿名函數(shù)的使用

    go語言匿名函數(shù)的使用

    今天小編就為大家分享一篇關(guān)于go語言匿名函數(shù)的使用,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04

最新評論

石城县| 武穴市| 广宁县| 绿春县| 雅江县| 岳西县| 天气| 拉萨市| 乌兰察布市| 浦县| 尚志市| 广河县| 凤翔县| 鄂托克前旗| 临城县| 清远市| 富平县| 乌拉特后旗| 南开区| 阳东县| 麦盖提县| 濮阳县| 东乡县| 苍溪县| 桓仁| 泸州市| 阿勒泰市| 静安区| 洪湖市| 辽源市| 徐州市| 随州市| 奉节县| 宜州市| 桂平市| 江安县| 那坡县| 璧山县| 黎平县| 蓝山县| 江永县|