Test-Driven Development - Go (6)
go
golang
TDD
Test-Driven Development
先分享一下 我自己在測試 Router 的 function 時,用來協助寫測試 function 的 Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package helper | |
import ( | |
"io" | |
"io/ioutil" | |
"net/http" | |
"net/http/httptest" | |
"testing" | |
"github.com/gin-gonic/gin" | |
) | |
type Request struct { | |
Method string | |
Path string | |
Headers map[string]string | |
Body io.Reader | |
} | |
type Response struct { | |
Code int | |
Body []byte | |
Err error | |
} | |
func TestApiCall(req Request, use []gin.HandlerFunc, handle gin.HandlerFunc) (res Response) { | |
resp := httptest.NewRecorder() | |
gin.SetMode(gin.TestMode) | |
_, router := gin.CreateTestContext(resp) | |
for _, element := range use { | |
router.Use(element) | |
} | |
router.POST(req.Path, handle) | |
request, err := http.NewRequest(req.Method, req.Path, req.Body) | |
if err != nil { | |
res.Err = err | |
return | |
} | |
for key, value := range req.Headers { | |
request.Header.Set(key, value) | |
} | |
router.ServeHTTP(resp, request) | |
res.Code = resp.Result().StatusCode | |
res.Body, res.Err = ioutil.ReadAll(resp.Result().Body) | |
return | |
} | |
func JudgementApicallResponse(t *testing.T, res Response, want Response) { | |
if res.Code != want.Code { | |
t.Errorf("status code should got %d, but got %d", want.Code, res.Code) | |
} | |
if res.Err != want.Err { | |
t.Errorf("err should got %d, but got %d", res.Err, want.Err) | |
} | |
if string(res.Body) != string(want.Body) { | |
t.Errorf("response body should got %s, but got %s", string(want.Body), string(res.Body)) | |
} | |
} |
26 行的 TestApiCall 是用來呼叫 你實際的 function 的
parameter:
req Request 這就是 api call 的參數 就不多做說明了
use []gin.HandlerFunc 這個會被放進 global middleware to the router. 可以操作 context
handle gin.HandlerFunc 這個是你實際要測試的 function
56 行的 JudgementApicallResponse 只是一個判斷輸入是否符合期待的 function
parameter:
t *testing.T 這是 go 內建的 test 就不多做說明
res Response 這個是 api call 得到的 result
want Response 這個是期待要拿到的結果
基本上每個 test case 都會呼叫到 TestApiCall
跟 JudgementApicallResponse
大量的減少了 test case 的 code
並且可以在觀看 test case 只需要專注在輸入輸出
算是方便的小工具了
打完收工