Gin使用

這裏的博客版本都不會被更新維護。查看最新的版本請移步: http://neojos.com

Ginnet/http包作了封裝,支持路由、中間件等特性,極大的方便對Http Server的開發。文章經過一個Test例子,來簡要介紹。對於特別基礎的部分,請閱讀參考文章。git

接口測試

Gotesting包爲程序自測提供了便利。能夠查閱以前寫的博客Go test基礎用法,對其內容,我仍是挺滿意的。github

使用Postman

對於接口測試,不少狀況都在使用Postman這樣的工具。首先在本地啓動服務,而後在Postman中配置請求的地址和參數、執行請求、查看結果。web

這種方式惟一讓人不滿意的地方在於:每次修改都須要重啓服務。跟直接執行一次Test相比,明顯多了一步。json

使用Test

測試基類

下面的代碼做爲接口測試的基類。app

TestMain中,咱們爲全部的測試用例指定通用的配置。以後在執行其餘Test前,都會先執行TestMain中的代碼。有效的避免了代碼冗餘。框架

getRouter方法用於返回一個gin的實例。咱們將服務的路由從新在Test中指定,並設置了中間件。函數

testHttpResponse是咱們請求處理的核心代碼,發送請求,並保存響應到w工具

//common_test.go

func TestMain(m *testing.M) {

    //聲明執行Test前的操做
    gin.SetMode(gin.TestMode)
    testutils.NewTestApp("../conf.test.toml")

    flag.Parse()
    os.Exit(m.Run())
}

//設置路由,獲取框架Gin的實例
func getRouter() *gin.Engine {
    router := gin.Default()

    //配置路由,這是我項目中的自定義配置
    router.Use(middleware.HeaderProcess())
    RouteAPI(router)

    return router
}

//統一處理請求返回結果
func testHttpResponse(t *testing.T, r *gin.Engine, req *http.Request, f func(w *httptest.ResponseRecorder) error) {
    w := httptest.NewRecorder()
    r.ServeHTTP(w, req)

    if err := f(w); err != nil {
        t.Fatal(err)
    }
}

測試用例

下面是具體的測試用例。咱們構造了一個Json數據格式的POST請求,而後經過調用testHttpResponse方法來讀取接口的響應數據。測試

關於NewRequest方法,它參數body傳遞一個io.Reader接口類型。從源代碼能夠看出,實現了該接口的分別是:bytes.Bufferbytes.Readerstrings.Readerui

func TestWeChatRecharge(t *testing.T) {
    router := getRouter()

    //構造json的請求體
    params := map[string]interface{}{
        "open_id":     "olFg1s3gPcISnooRX9WSkX_E-cww",
        "device_type": "ANDROID",
    }
    jsonParams, _ := json.Marshal(params)
    readParams := bytes.NewReader(jsonParams)
    req, _ := http.NewRequest("POST", "/pay/wx/recharge", readParams)
    req.Header.Set("Content-type", "application/json")

    //發送請求
    testHttpResponse(t, router, req, func(w *httptest.ResponseRecorder) error {
        p, err := ioutil.ReadAll(w.Body)
        if err != nil {
            return err
        }

        t.Logf("%+v", string(p))
        return nil
    })
}

小結

經過上述的步驟,咱們實現了直接在Test中作接口測試。

Middleware

聲明一個middleware函數,返回類型爲type HandlerFunc func(*Context)

func setUserStatus() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Println("set status")
    }
}

若是須要將函數應用於全部的請求,使用Use方法。好比統一的請求頭轉換、錯誤輸出、日誌打印等

//Use adds middleware to the group
router.Use(setUserStatus())

下面是給具體的請求設置中間件。從這裏能夠看出,中間件處理函數和正常的業務處理函數類型是相同的。

//Use a particular middleware
articleRoutes.GET("/create", setUserStatus(), showArticleCreationPage)

最後系統依次調用註冊的handler完成請求處理:

func (c *Context) Next() {
    c.index++
    for s := int8(len(c.handlers)); c.index < s; c.index++ {
        c.handlers[c.index](c)
    }
}

參考文章:

  1. Building Go Web Applications and Microservices Using Gin
  2. Test-driven Development of Go Web Applications with Gin
相關文章
相關標籤/搜索