Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making ioutil.ReadAll(response.Body) throw error in golang

For some reason, I cannot seem to get ioutil.ReadAll(res.Body), where res is the *http.Response returned by res, err := hc.Do(redirectRequest) (for hc http.Client, redirectRequest *http.Request).

Testing strategy thus far

Any time I see hc.Do or http.Request in the SUT, my instinct is to spin up a fake server and point the appropriate application states to it. Such a server, for this test, looks like this :

badServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
    // some stuff
    w.Write([some bad bytes])
}))
defer badServer.Close()

I don't seem to have a way to control res.Body, which is literally the only thing keeping me from 100% test completion against the func this is all in.

I tried, in the errorThrowingServer's handler func, setting r.Body to a stub io.ReadCloser that throws an error when Read() is called, but that doesn't effect res.

like image 612
Mike Warren Avatar asked Jan 28 '26 13:01

Mike Warren


1 Answers

You can mock the body. Basically body is an io.ReadCloser interface so, you can do something like this:

import (
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

type mockReadCloser struct {
    mock.Mock
}

func (m *mockReadCloser) Read(p []byte) (n int, err error) {
    args := m.Called(p)
    return args.Int(0), args.Error(1)
}

func (m *mockReadCloser) Close() error {
    args := m.Called()
    return args.Error(0)
}

func TestTestingSomethingWithBodyError(t *testing.T) {
    mockReadCloser := mockReadCloser{}
    // if Read is called, it will return error
    mockReadCloser.On("Read", mock.AnythingOfType("[]uint8")).Return(0, fmt.Errorf("error reading"))
    // if Close is called, it will return error
    mockReadCloser.On("Close").Return(fmt.Errorf("error closing"))

    request := &http.Request{
        // pass the mock address
        Body: &mockReadCloser,
    }

    expected := "what you expected"
    result := YourMethod(request)

    assert.Equal(t, expected, result)

    mockReadCloser.AssertExpectations(t)
}

To stop reading you can use:

mockReadCloser.On("Read", mock.AnythingOfType("[]uint8")).Return(0, io.EOF).Once()
like image 175
Piero Avatar answered Jan 31 '26 07:01

Piero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!