2017-07-16 94 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

相关问题