Skip to content

Commit 51209cb

Browse files
feat: Unit tests for basic functionality
1 parent e3b1f42 commit 51209cb

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,38 @@
11
# errhandler
22
Wraps Go's http.HandlerFunc, allowing for simpler use of http.NewServeMux().
3+
4+
### Install
5+
6+
```sh
7+
go get github.com/codingconcepts/errhandler
8+
```
9+
10+
### Usage
11+
12+
Wrap Go's stdlib `http.HandlerFunc` using `errhandler.Wrap()`:
13+
14+
```go
15+
mux := http.NewServeMux()
16+
mux.Handle("GET /products/{id}", errhandler.Wrap(getProduct))
17+
```
18+
19+
Update your existing handler signature, by adding an `error` return type:
20+
21+
```go
22+
func addProduct(w http.ResponseWriter, r *http.Request) error {
23+
...
24+
}
25+
```
26+
27+
Utilize the `ParseJSON` and `SendJSON` functions to reduce the amount of boilerplate code handlers require:
28+
29+
``` go
30+
var p product
31+
if err := errhandler.ParseJSON(r, &p); err != nil {
32+
return fmt.Errorf("parsing request json: %w", err)
33+
}
34+
35+
products[p.ID] = p
36+
37+
return errhandler.SendJSON(w, p)
38+
```

errhandler_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package errhandler
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"net/http/httptest"
9+
"strings"
10+
"testing"
11+
)
12+
13+
// TestWrap_ServeHTTP tests the ServeHTTP method of the Wrap type.
14+
func TestWrap_ServeHTTP(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
body string
18+
handler Wrap
19+
expectedStatus int
20+
expectedBody string
21+
}{
22+
{
23+
name: "parse json without error",
24+
body: `{"a": 1}`,
25+
handler: Wrap(func(w http.ResponseWriter, r *http.Request) error {
26+
m := map[string]int{}
27+
28+
return ParseJSON(r, &m)
29+
}),
30+
expectedStatus: http.StatusOK,
31+
expectedBody: "",
32+
},
33+
{
34+
name: "parse json with error",
35+
body: "a",
36+
handler: Wrap(func(w http.ResponseWriter, r *http.Request) error {
37+
m := map[string]int{}
38+
39+
return ParseJSON(r, &m)
40+
}),
41+
expectedStatus: http.StatusInternalServerError,
42+
expectedBody: "invalid character 'a' looking for beginning of value\n",
43+
},
44+
{
45+
name: "send string without error",
46+
handler: Wrap(func(w http.ResponseWriter, r *http.Request) error {
47+
return SendString(w, "test")
48+
}),
49+
expectedStatus: http.StatusOK,
50+
expectedBody: "test",
51+
},
52+
{
53+
name: "send json without error",
54+
handler: Wrap(func(w http.ResponseWriter, r *http.Request) error {
55+
return SendJSON(w, map[string]int{"a": 1})
56+
}),
57+
expectedStatus: http.StatusOK,
58+
expectedBody: "{\"a\":1}\n",
59+
},
60+
{
61+
name: "error",
62+
handler: Wrap(func(w http.ResponseWriter, r *http.Request) error {
63+
return fmt.Errorf("error doing stuff: %w", errors.New("database error"))
64+
}),
65+
expectedStatus: http.StatusInternalServerError,
66+
expectedBody: "error doing stuff: database error\n",
67+
},
68+
}
69+
70+
for _, tt := range tests {
71+
t.Run(tt.name, func(t *testing.T) {
72+
var body io.Reader
73+
if tt.body != "" {
74+
body = strings.NewReader(tt.body)
75+
}
76+
77+
req := httptest.NewRequest(http.MethodGet, "http://example.com/foo", body)
78+
w := httptest.NewRecorder()
79+
80+
tt.handler.ServeHTTP(w, req)
81+
82+
res := w.Result()
83+
defer res.Body.Close()
84+
85+
if res.StatusCode != tt.expectedStatus {
86+
t.Errorf("expected status %d, got %d", tt.expectedStatus, res.StatusCode)
87+
}
88+
89+
actualBody := w.Body.String()
90+
if actualBody != tt.expectedBody {
91+
t.Errorf("expected body %q, got %q", tt.expectedBody, actualBody)
92+
}
93+
})
94+
}
95+
}

0 commit comments

Comments
 (0)