Created
January 2, 2019 19:51
-
-
Save rgorsuch/0044c3eca91aaf04728ab60e8799cc0a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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