Skip to content

Commit 4a8cb2b

Browse files
committed
feat(exp): add mock utils package
1 parent 8c7f5b3 commit 4a8cb2b

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

hcloud/exp/kit/mockutils/mockutils.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package mockutils
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
// Request describes a http request that a [httptest.Server] should receive, and the
12+
// corresponding response to return.
13+
//
14+
// Additional checks on the request (e.g. request body) may be added using
15+
// [Request.Want] function.
16+
//
17+
// The response body is populated from either a JSON struct, or a JSON string.
18+
type Request struct {
19+
Method string
20+
Path string
21+
Want func(t *testing.T, r *http.Request)
22+
23+
Status int
24+
JSON any
25+
JSONRaw string
26+
}
27+
28+
// Handler is used with a [httptest.Server] to mock http requests provided by the user.
29+
//
30+
// Request matching is based on the request count, and the user provided request will be
31+
// iterated over.
32+
func Handler(t *testing.T, requests []Request) http.HandlerFunc {
33+
t.Helper()
34+
35+
index := 0
36+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
37+
if testing.Verbose() {
38+
t.Logf("call %d: %s %s\n", index, r.Method, r.URL.Path)
39+
}
40+
41+
if index >= len(requests) {
42+
t.Fatalf("received unknown call %d", index)
43+
}
44+
45+
response := requests[index]
46+
assert.Equal(t, response.Method, r.Method)
47+
assert.Equal(t, response.Path, r.RequestURI)
48+
49+
if response.Want != nil {
50+
response.Want(t, r)
51+
}
52+
53+
w.WriteHeader(response.Status)
54+
switch {
55+
case response.JSON != nil:
56+
w.Header().Set("Content-Type", "application/json")
57+
if err := json.NewEncoder(w).Encode(response.JSON); err != nil {
58+
t.Fatal(err)
59+
}
60+
case response.JSONRaw != "":
61+
w.Header().Set("Content-Type", "application/json")
62+
_, err := w.Write([]byte(response.JSONRaw))
63+
if err != nil {
64+
t.Fatal(err)
65+
}
66+
}
67+
68+
index++
69+
})
70+
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package mockutils
2+
3+
import (
4+
"io"
5+
"net/http"
6+
"net/http/httptest"
7+
"strings"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestHandler(t *testing.T) {
15+
server := httptest.NewServer(Handler(t, []Request{
16+
{
17+
Method: "GET", Path: "/",
18+
Status: 200,
19+
JSON: struct {
20+
Data string `json:"data"`
21+
}{
22+
Data: "Hello",
23+
},
24+
},
25+
{
26+
Method: "GET", Path: "/",
27+
Status: 400,
28+
JSONRaw: `{"error": "failed"}`,
29+
},
30+
}))
31+
defer server.Close()
32+
33+
// Request 1
34+
resp, err := http.Get(server.URL)
35+
require.NoError(t, err)
36+
assert.Equal(t, 200, resp.StatusCode)
37+
assert.Equal(t, `{"data":"Hello"}`, readBody(t, resp))
38+
39+
// Request 2
40+
resp, err = http.Get(server.URL)
41+
require.NoError(t, err)
42+
assert.Equal(t, 400, resp.StatusCode)
43+
assert.Equal(t, `{"error": "failed"}`, readBody(t, resp))
44+
}
45+
46+
func readBody(t *testing.T, resp *http.Response) string {
47+
t.Helper()
48+
49+
body, err := io.ReadAll(resp.Body)
50+
require.NoError(t, err)
51+
require.NoError(t, resp.Body.Close())
52+
return strings.TrimSuffix(string(body), "\n")
53+
}

0 commit comments

Comments
 (0)