How do I check for an error while reading from the request body?

I am writing unit tests for http Handlers in golang. When reviewing the code coverage reports, I ran into the following problem: when reading the request body from the request, it ioutil.ReadAll

may return an error that I need to handle. However, when I write unit tests for my handler, I have no idea how to send a request to my handler in such a way that it throws an error like this (premature end of content does not seem to generate such an error, but will cause errors on unwinding the body). This is what I am trying to do:

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...
}

      

How can I write a test case for HandlePostRequest

that also covers the case of bytesErr

not being nil

?

+5


source to share


1 answer


You can create and use a faked one by yourself that intentionally returns an error when reading its body. You don't necessarily need a new request, a faulty body (this ) is enough . http.Request

io.ReadCloser

httptest.NewRequest()

this is using a function where you can pass a value to be used (wrapped as ) as the request body. httptest.NewRequest()

httptest.NewRequest()

io.Reader

io.ReadCloser

Here's an example io.Reader

that intentionally returns an error when trying to read from it:

type errReader int

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

      

An example that will cover your error case:



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

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

      

Conclusion (try on Go Playground ):

Error reading the body: test error

      

See the related question if you need to simulate reading errors from the response body (rather than from the request body): How to cause an error when reading the response body

+16


source







All Articles