go-kit/test/httpmock_test.go

284 lines
6.2 KiB
Go

package test_test
import (
"bytes"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/textproto"
"net/url"
"testing"
"go-mod.ewintr.nl/go-kit/test"
)
func TestHTTPMock(t *testing.T) {
procs := []test.MockServerProcedure{
test.MockServerProcedure{
URI: "/",
HTTPMethod: "GET",
Response: test.MockResponse{
Body: []byte("getRoot"),
},
},
test.MockServerProcedure{
URI: "/",
HTTPMethod: "POST",
Response: test.MockResponse{
Body: []byte("postRoot"),
},
},
test.MockServerProcedure{
URI: "/get/header",
HTTPMethod: "GET",
Response: test.MockResponse{
StatusCode: http.StatusAccepted,
Headers: http.Header{
"some-key": []string{"some-value"},
},
Body: []byte("getResponseHeader"),
},
},
test.MockServerProcedure{
URI: "/get/auth",
HTTPMethod: "GET",
Response: test.MockResponse{
Body: []byte("getRootAuth"),
},
},
test.MockServerProcedure{
URI: "/my_account",
HTTPMethod: "GET",
Response: test.MockResponse{
Body: []byte("getAccount"),
},
},
test.MockServerProcedure{
URI: "/my_account.json",
HTTPMethod: "GET",
Response: test.MockResponse{
Body: []byte("getAccountJSON"),
},
},
}
var record test.MockAssertion
testMockServer := test.NewMockServer(&record, procs...)
type mockRequest struct {
uri string
method string
user, password string
header http.Header
body []byte
hits int
}
canonical := textproto.CanonicalMIMEHeaderKey
for _, tc := range []struct {
m string
request mockRequest
response test.MockResponse
}{
{
m: "method get root path",
request: mockRequest{
uri: "/",
method: http.MethodGet,
hits: 2,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("getRoot"),
},
},
{
m: "method get root path with headers",
request: mockRequest{
uri: "/",
method: http.MethodGet,
header: http.Header{
canonical("input-header-key"): []string{"Just the Value"},
},
hits: 2,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("getRoot"),
},
},
{
m: "method get root path with body",
request: mockRequest{
uri: "/",
method: http.MethodGet,
body: []byte("input"),
hits: 2,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("getRoot"),
},
},
{
m: "method get root path with headers and body",
request: mockRequest{
uri: "/",
method: http.MethodGet,
header: http.Header{
canonical("input-header-key"): []string{"Just the Value"},
},
body: []byte("input"),
hits: 2,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("getRoot"),
},
},
{
m: "method post root path",
request: mockRequest{
uri: "/",
method: http.MethodPost,
hits: 2,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("postRoot"),
},
},
{
m: "method post root path with basic authentication",
request: mockRequest{
uri: "/",
method: http.MethodPost,
user: "my-user",
password: "my-password",
hits: 1,
},
response: test.MockResponse{
StatusCode: http.StatusOK,
Body: []byte("postRoot"),
},
},
{
m: "unmatched uri path",
request: mockRequest{
uri: "/unmatched",
method: http.MethodGet,
hits: 0,
},
response: test.MockResponse{
StatusCode: http.StatusNotFound,
Body: []byte{},
},
},
} {
t.Run(tc.m, func(t *testing.T) {
test.OK(t, record.Reset())
for _ = range make([]int, tc.request.hits) {
url, errU := url.Parse(testMockServer.URL + tc.request.uri)
test.OK(t, errU)
req, errReq := http.NewRequest(
tc.request.method,
url.String(),
bytes.NewReader(tc.request.body),
)
test.OK(t, errReq)
for k, v := range tc.request.header {
req.Header[k] = v
}
// testing authentication in the request
if len(tc.request.user) > 0 || len(tc.request.password) > 0 {
req.SetBasicAuth(tc.request.user, tc.request.password)
if tc.request.header == nil {
tc.request.header = make(http.Header)
}
auth := tc.request.user + ":" + tc.request.password
tc.request.header["Authorization"] = []string{
fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth)))}
}
client := new(http.Client)
resp, errResp := client.Do(req)
test.OK(t, errResp)
actualBody, err := ioutil.ReadAll(resp.Body)
test.OK(t, err)
defer resp.Body.Close()
test.Equals(t, tc.response.StatusCode, resp.StatusCode)
test.Equals(t, tc.response.Body, actualBody)
}
test.Equals(t, tc.request.hits, record.Hits(tc.request.uri, tc.request.method))
// assert if all request had the correct header
for _, h := range record.Headers(tc.request.uri, tc.request.method) {
test.Equals(t, tc.request.header, h)
}
// assert if all request had the correct body
for _, b := range record.Body(tc.request.uri, tc.request.method) {
test.Equals(t, tc.request.body, b)
}
})
}
}
func ExampleMockAssertion_Hits() {
var record test.MockAssertion
uri := "/"
server := test.NewMockServer(&record, test.MockServerProcedure{
URI: uri,
HTTPMethod: http.MethodGet,
})
http.Get(server.URL)
fmt.Println(record.Hits(uri, http.MethodGet))
// Output: 1
}
func ExampleMockAssertion_Headers() {
var record test.MockAssertion
uri := "/"
server := test.NewMockServer(&record, test.MockServerProcedure{
URI: uri,
HTTPMethod: http.MethodPost,
})
http.Post(server.URL, "application/json", nil)
fmt.Println(record.Headers(uri, http.MethodPost))
// Output: [map[Content-Type:[application/json]]]
}
func ExampleMockAssertion_Body() {
var record test.MockAssertion
uri := "/"
server := test.NewMockServer(&record, test.MockServerProcedure{
URI: uri,
HTTPMethod: http.MethodPost,
})
http.Post(server.URL, "text/plain", bytes.NewBufferString("hi there"))
for _, b := range record.Body(uri, http.MethodPost) {
fmt.Println(string(b))
}
// Output: hi there
}