2017-07-16 47 views
2

我正在爲golang中的http Handlers編寫單元測試。查看代碼覆蓋率報告時,我遇到了以下問題:從請求中讀取請求正文時,ioutil.ReadAll可能會返回我需要處理的錯誤。然而,當我爲我的處理程序編寫單元測試時,我不知道如何發送請求給我的處理程序,以便它會觸發這樣的錯誤(內容的提前結束似乎不會產生這樣的錯誤,但會產生錯誤解組身體)。這就是我要做的:如何在從請求主體讀取時測試錯誤?

package demo 

import (
    "bytes" 
    "io/ioutil" 
    "net/http" 
    "net/http/httptest" 
    "testing" 
) 

func HandlePostRequest(w http.ResponseWriter, r *http.Request) { 
    body, bytesErr := ioutil.ReadAll(r.Body) 
    if bytesErr != nil { 
     // intricate logic goes here, how can i test it? 
     http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 
     return 
    } 
    defer r.Body.Close() 
    // continue... 
} 

func TestHandlePostRequest(t *testing.T) { 
    ts := httptest.NewServer(http.HandlerFunc(HandlePostRequest)) 
    data, _ := ioutil.ReadFile("testdata/fixture.json") 
    res, err := http.Post(ts.URL, "application/json", bytes.NewReader(data)) 
    // continue... 
} 

我怎麼能寫HandlePostRequest一個測試用例還包括bytesErr不是nil的情況下?

回答

4

您可以創建並使用由您僞造的http.Request,它在讀取其主體時故意返回錯誤。你不一定需要一個全新的請求,一個錯誤的機構就足夠了(這是一個io.ReadCloser)。

最簡單的方法是使用httptest.NewRequest()函數,您可以將io.Reader的值傳遞給請求主體(包裝爲io.ReadCloser)。

下面是一個例子io.Reader其有意返回試圖從中讀取數據時的錯誤:

type errReader int 

func (errReader) Read(p []byte) (n int, err error) { 
    return 0, errors.New("test error") 
} 

例,將覆蓋你的錯誤案例:

func HandlePostRequest(w http.ResponseWriter, r *http.Request) { 
    body, err := ioutil.ReadAll(r.Body) 
    if err != nil { 
     fmt.Printf("Error reading the body: %v\n", err) 
     return 
    } 
    defer r.Body.Close() 
    fmt.Printf("No error, body: %s\n", body) 
} 

func main() { 
    testRequest := httptest.NewRequest(http.MethodPost, "/something", errReader(0)) 
    HandlePostRequest(nil, testRequest) 
} 

輸出(嘗試在Go Playground) :

Error reading the body: test error 
+0

很好的答案,正是我所期待的。 return語句存在於我的真實代碼中,但感謝無論如何陳述它,我會將其添加到該問題中以避免其他人混淆。 – m90

相關問題