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
?
source to share
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
source to share