linnic
linnic

Reputation: 469

Golang: mock response testing http client

i'm new to Golang and i'm trying to write a test for a simple HTTP client. i read a lot of ways of doing so also here in SO but none of them seems to work. I'm having troubles mocking the client response

This is how my client looks right now:

type API struct {
    Client  *http.Client
}

func (api *API) MyClient(qp string) ([]byte, error) {
    url := fmt.Sprintf("http://localhost:8000/myapi?qp=%s", qp)
    resp, err := api.Client.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    // handling error and doing stuff with body that needs to be unit tested
    if err != nil {
        return nil, err
    }
    return body, err
}

And this is my test function:

func TestDoStuffWithTestServer(t *testing.T) {
    // Start a local HTTP server
    server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        rw.Write([]byte(`OK`))
    }))
    defer server.Close()

    // Use Client & URL from our local test server
    api := API{server.Client()}
    body, _ := api.MyClient("1d")



    fmt.Println(body)

}    

As i said, this is how they look right cause i try lot of ways on doing so.

My problem is that i'm not able to mock the client respose. in this example my body is empty. my understanding was that rw.Write([]byte(OK)) should mock the response 🤔

Upvotes: 1

Views: 6543

Answers (1)

linnic
linnic

Reputation: 469

In the end i solved it like this:

myclient:

type API struct {
    Endpoint string
}

func (api *API) MyClient(slot string) ([]byte, error) {
    url := fmt.Sprintf("%s/myresource?qp=%s", api.Endpoint, slot)
    c := http.Client{}
    resp, err := c.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return body, err
}

test:

func TestDoStuffWithTestServer(t *testing.T) {
    server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        rw.Write([]byte(`{Result: [{Cluster_name: "cl1", Pings: 2}]}`))
    }))

    defer server.Close()

    api := API{Endpoint: server.URL}
    res, _ := api.MyClient("1d")

    expected := []byte(`{Result: [{Cluster_name: "cl1", Pings: 2}]}`)

    if !bytes.Equal(expected, res) {
        t.Errorf("%s != %s", string(res), string(expected))
    }
}

still, not 100% sure is the right way of doing so in Go

Upvotes: 2

Related Questions