這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
我們用go開發一個Web Server後,打算單元測試寫的handler函數,在不知道httptest之前,使用比較笨的方法
就是編譯運行該Web Server後,再用go編寫一個用戶端程式向該Web Server對應的route發送資料然後解析
返回的資料。這個方法測試時非常麻煩,使用httptest來測試的話就非常簡單,可以和testing測試一起使用。
httptest基本使用方法
假設在server中handler已經寫好
http.HandleFunc("/health-check", HealthCheckHandler)func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { // A very simple health check. w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") // In the future we could report back on the status of our DB, or our cache // (e.g. Redis) by performing a simple PING, and include them in the response. io.WriteString(w, `{"alive": true}`)}
測試如下:
import ( "net/http" "net/http/httptest" "testing")func TestHealthCheckHandler(t *testing.T) { //建立一個請求 req, err := http.NewRequest("GET", "/health-check", nil) if err != nil { t.Fatal(err) } // 我們建立一個 ResponseRecorder (which satisfies http.ResponseWriter)來記錄響應 rr := httptest.NewRecorder() //直接使用HealthCheckHandler,傳入參數rr,req HealthCheckHandler(rr, req) // 檢測返回的狀態代碼 if status := rr.Code; status != http.StatusOK { t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) } // 檢測返回的資料 expected := `{"alive": true}` if rr.Body.String() != expected { t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) }}
然後就可以使用run test來執行測試.
如果Web Server有操作資料庫的行為,需要在init函數中進行資料庫的串連。
參考官方文檔中的範例編寫的另外一個測試代碼:
func TestHealthCheckHandler2(t *testing.T) { reqData := struct { Info string `json:"info"` }{Info: "P123451"} reqBody, _ := json.Marshal(reqData) fmt.Println("input:", string(reqBody)) req := httptest.NewRequest( http.MethodPost, "/health-check", bytes.NewReader(reqBody), ) req.Header.Set("userid", "wdt") req.Header.Set("commpay", "brk") rr := httptest.NewRecorder() HealthCheckHandler(rr, req) result := rr.Result() body, _ := ioutil.ReadAll(result.Body) fmt.Println(string(body)) if result.StatusCode != http.StatusOK { t.Errorf("expected status 200,",result.StatusCode) }}
注意不同的地方
- http.NewRequest替換為httptest.NewRequest。
- httptest.NewRequest的第三個參數可以用來傳遞body資料,必須實現io.Reader介面。
- httptest.NewRequest不會返回error,無需進行err!=nil檢查。
- 解析響應時沒直接使用ResponseRecorder,而是調用了Result函數。
參考
httptest doc
Testing Your (HTTP) Handlers in Go