Skip to content

Instantly share code, notes, and snippets.

@rgorsuch
Created January 2, 2019 19:51
Show Gist options
  • Save rgorsuch/0044c3eca91aaf04728ab60e8799cc0a to your computer and use it in GitHub Desktop.
Save rgorsuch/0044c3eca91aaf04728ab60e8799cc0a to your computer and use it in GitHub Desktop.
package http_test
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/pkg/errors"
"github.com/golang/mock/gomock"
. "github.com/smartystreets/goconvey/convey"
)
// HTTP Client Transport Recorder
type roundTripRecorder struct {
http.RoundTripper
request *http.Request
response *http.Response
err error
}
func (r *roundTripRecorder) RoundTrip(req *http.Request) (*http.Response, error) {
r.request = req
return r.response, r.err
}
func newMockHTTPClient(code int, body string, err error) (*http.Client, *roundTripRecorder) {
response := &http.Response{
StatusCode: code,
Status: http.StatusText(code),
Body: ioutil.NopCloser(strings.NewReader(body)),
}
recorder := roundTripRecorder{
response: response,
err: err,
}
return &http.Client{
Transport: &recorder,
}, &recorder
}
func TestHTTPServer_Addr(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Convey("Intercept an HTTP Server", t, func() {
toReadCloser := func(body string) io.ReadCloser {
return ioutil.NopCloser(strings.NewReader(body))
}
url := "http://localhost/thumbs"
body := `{ "user": "guid" }`
request, _ := http.NewRequest("POST", url, toReadCloser(body))
response := httptest.NewRecorder()
testSubject := &ServerUnderTest{}
testSubject.ServeHTTP(response, request)
So(response.Code, ShouldEqual, http.StatusOK)
})
Convey("Intercept an HTTP Client", t, func() {
mockHTTPClient, recorder := newMockHTTPClient(200, `{ "Total": 42 }`, nil)
testSubject := ClientUnderTest{client: mockHTTPClient}
response, err := testSubject.PerformWork()
So(recorder.request.URL.Scheme, ShouldEqual, "http")
So(response, ShouldResemble, &Resource{Total: 42})
So(err, ShouldBeNil)
})
}
// Sample Implementation Under Test
type ServerUnderTest struct{}
func (s *ServerUnderTest) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/thumbs" {
_, _ = w.Write([]byte("up"))
} else {
http.Error(w, "not implemented", http.StatusNotFound)
}
}
type ClientUnderTest struct {
client *http.Client
}
type Resource struct {
Total int
}
func (c *ClientUnderTest) PerformWork() (*Resource, error) {
response, err := c.client.Get("http://host/api/resource")
if err != nil {
return nil, errors.Wrap(err, "failed to get resource")
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body")
}
resource := Resource{}
err = json.Unmarshal(body, &resource)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal response body")
}
return &resource, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment