這裏的博客版本都不會被更新維護。查看最新的版本請移步: http://neojos.com
Gin
對net/http
包作了封裝,支持路由、中間件等特性,極大的方便對Http Server
的開發。文章經過一個Test
例子,來簡要介紹。對於特別基礎的部分,請閱讀參考文章。git
Go
中testing
包爲程序自測提供了便利。能夠查閱以前寫的博客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.Buffer
、bytes.Reader
、strings.Reader
。ui
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) } }
參考文章: