Skip to content

Commit

Permalink
feat(exp): add mock utils package (#460)
Browse files Browse the repository at this point in the history
Test helper to mock http request made with the hcloud-go library.
  • Loading branch information
jooola authored Jun 18, 2024
1 parent 8c7f5b3 commit 92f7c62
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
72 changes: 72 additions & 0 deletions hcloud/exp/mockutils/mockutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package mockutils

import (
"encoding/json"
"net/http"
"testing"

"github.com/stretchr/testify/require"
)

// Request describes a http request that a [httptest.Server] should receive, and the
// corresponding response to return.
//
// Additional checks on the request (e.g. request body) may be added using the
// [Request.Want] function.
//
// The response body is populated from either a JSON struct, or a JSON string.
type Request struct {
Method string
Path string
Want func(t *testing.T, r *http.Request)

Status int
JSON any
JSONRaw string
}

// Handler is used with a [httptest.Server] to mock http requests provided by the user.
//
// Request matching is based on the request count, and the user provided request will be
// iterated over.
func Handler(t *testing.T, requests []Request) http.HandlerFunc {
t.Helper()

index := 0
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if testing.Verbose() {
t.Logf("call %d: %s %s\n", index, r.Method, r.RequestURI)
}

if index >= len(requests) {
t.Fatalf("received unknown call %d", index)
}

expected := requests[index]
require.Equal(t,
expected.Method+" "+expected.Path,
r.Method+" "+r.RequestURI,
)

if expected.Want != nil {
expected.Want(t, r)
}

w.WriteHeader(expected.Status)
switch {
case expected.JSON != nil:
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(expected.JSON); err != nil {
t.Fatal(err)
}
case expected.JSONRaw != "":
w.Header().Set("Content-Type", "application/json")
_, err := w.Write([]byte(expected.JSONRaw))
if err != nil {
t.Fatal(err)
}
}

index++
})
}
53 changes: 53 additions & 0 deletions hcloud/exp/mockutils/mockutils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package mockutils

import (
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestHandler(t *testing.T) {
server := httptest.NewServer(Handler(t, []Request{
{
Method: "GET", Path: "/",
Status: 200,
JSON: struct {
Data string `json:"data"`
}{
Data: "Hello",
},
},
{
Method: "GET", Path: "/",
Status: 400,
JSONRaw: `{"error": "failed"}`,
},
}))
defer server.Close()

// Request 1
resp, err := http.Get(server.URL)
require.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, `{"data":"Hello"}`, readBody(t, resp))

// Request 2
resp, err = http.Get(server.URL)
require.NoError(t, err)
assert.Equal(t, 400, resp.StatusCode)
assert.Equal(t, `{"error": "failed"}`, readBody(t, resp))
}

func readBody(t *testing.T, resp *http.Response) string {
t.Helper()

body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
return strings.TrimSuffix(string(body), "\n")
}

0 comments on commit 92f7c62

Please sign in to comment.