httptest 的介紹與使用

在寫完接口以後都須要對接口進行測試,在 golang 標準庫中提供 httptest 包來輔助測試。golang

由於接口都是須要 IP 地址或域名來訪問,httptest 包中默認定義了服務地址json

const DefaultRemoteAddr = "1.2.3.4"

重要的方法

NewRequest(請求體)

NewRequest 方法用來建立一個 http 的請求體。api

方法定義:app

func NewRequest(method, target string, body io.Reader) *http.Request
  • method 參數表示測試的接口的 HTTP 方法。
  • target 參數表示接口定義的路由。
  • body 參數表示請求體。

NewRecorder(響應體)

方法定義:框架

func NewRecorder() *ResponseRecorder

NewRecorder 方法用來建立 http 的響應體。返回的類型是 *httptest.ResponseRecorder ,包含接口返回信息,等價於 http.ResponseWriter單元測試

ResponseRecorder類型定義:測試

type ResponseRecorder struct {
        // http 響應碼.
        Code int
        // 頭部信息
        HeaderMap http.Header
        // 返回的 Body
        Body *bytes.Buffer
        // 是否調用 Flush 方法
        Flushed bool
}

NewServer(http服務)

方法定義:code

func NewServer(handler http.Handler) *Server

NewServer 方法用來建立和啓動新的服務。同類的還有 NewTLSServer,用來建立帶 SSL 的服務。router

type Server struct {
        URL      string // 服務地址
        Listener net.Listener
        // TLS 配置信息
        TLS *tls.Config
        Config *http.Server
}

測試 next/http 庫建立的接口

請求接口定義:server

func testAPI(w http.ResponseWriter, r *http.Request){}

測試方法定義:

func Test_testApi(t *testing.T) {
    tests := []struct {
        name string
    }{
        {
            name: "test api",
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            ts := httptest.NewServer(http.HandlerFunc(testAPI))
            defer ts.Close()

            params := struct{
                "params" string 
            }{
                "params": "paramsBody"
            }
            paramsByte, _ := json.Marshal(params)

            resp, err := http.Post(tserver.URL, "application/json", bytes.NewBuffer(paramsByte))
            if err != nil {
                t.Error(err)
            }
            defer resp.Body.Close()

            t.Log(resp.StatusCode)
            if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
                body, _ := ioutil.ReadAll(resp.Body)
                t.Error(string(body))
            }
        })
    }
}

測試時經過 httptest.NewServer 建立一個 testAPI 接口的服務。而後經過 http.Post 方法來調用咱們建立的服務,達到接口測試時請求的目的。而後判斷接口返回的信息是否正確。

測試 Gin 框架的接口

請求接口定義:

func testAPI(ctx *gin.Context){}

測試方法定義:

func Test_testAPI(t *testing.T) {
    // 定義路由
    router := gin.Default()
    router.POST("/test", testAPI)

    tests := []struct {
        name string
    }{
        {
            name: "test api",
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            params := struct{
                "params" string 
            }{
                "params": "paramsBody"
            }
            paramsByte, _ := json.Marshal(params)
            w := httptest.NewRecorder()
            req := httptest.NewRequest("POST", "/test", bytes.NewBuffer(paramsByte))
            setup.api.router.ServeHTTP(w, req)

            assert.Equal(t, http.StatusOK, w.Code)

            result, _ := ioutil.ReadAll(w.Body)
            var ret model.MessageResult
            if err := json.Unmarshal(result, &ret); err != nil {
                t.Error(err)
            }
            assert.Equal(t, tt.want, ret)
        })
    }
}

測試時須要定義好 gin 的路由,而後建立 httptest.NewRecorder 和 httptest.NewRequest 對象,並調用 gin 路由的 ServeHTTP 方法來執行接口。

ServeHTTP 是 *gin.Engine 實現了 http.Handler 接口。經過這種方式達到請求接口目的。而後判斷接口返回的信息是否正確。

小結

接口的測試在開發當中是十分重要,我這裏介紹了使用 net/http 和 gin 建立接口的測試用例。

經過 httptest 包能方便的對接口進行單元測試,而不須要單獨的起一個服務來進行測試。

Ref

相關文章
相關標籤/搜索