Stubbing out the Go http.Client to test an HTTP HandlerFunc

Featured image for sharing metadata for article

If you're writing Go tests that interact with an API, at some point you'll want to fully test your built API, but don't necessarily want to have the server actually running + interacting with real dependencies.

For instance, you may be wanting to use a generated OpenAPI client, but want to test it against your configured server's ServeHTTP function instead of executing the service for real.

Note that this is a separate set of testing to just testing the handlers in isolation, where we'd be able to unit test just those method calls. In this version, we're testing that the fully configured router works as expected, with i.e. an OpenAPI client.

It's actually pretty straightforward by taking advantage of Go's httptest package, and interface types, which allow us to write the following:

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gorilla/mux"
	// this would also include the `api` package, which is expected to contain the `oapi-codegen`'d API client
)

type server interface {
	ServeHTTP(w http.ResponseWriter, r *http.Request)
}

type fakeClient struct {
	server server
}

func (c *fakeClient) Do(r *http.Request) (*http.Response, error) {
	rr := httptest.NewRecorder()
	c.server.ServeHTTP(rr, r)
	return rr.Result(), nil
}

func TestRouter(t *testing.T) {
	var server server
	// construct the server i.e. by `mux.NewRouter()`

	fakeClient := fakeClient{
		server: server,
	}

	client, err := api.NewClientWithResponses("", api.WithHTTPClient(&fakeClient))

	resp, err := client.Healthcheck(context.TODO())
	if err != nil {
		t.Errorf(err.Error())
	}
	if 200 != resp.StatusCode {
		t.Errorf("Expected status code 200, but was %d", resp.StatusCode)
	}
}

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #go.

Also on:

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.