Handler Tests
Table-driven tests for bookmark handlers using httptest and closure-based handlers.
package main
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func assertStatus(t *testing.T, got, want int) {
t.Helper()
if got != want {
t.Errorf("status = %d, want %d", got, want)
}
}
func doRequest(t *testing.T, mux http.Handler, method, path string, body string) *httptest.ResponseRecorder {
t.Helper()
var reader *strings.Reader
if body != "" {
reader = strings.NewReader(body)
}
req := httptest.NewRequest(method, path, reader)
if body != "" {
req.Header.Set("Content-Type", "application/json")
}
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
return rec
}
func TestCreateBookmark(t *testing.T) {
db := setupTestDB(t)
store := NewBookmarkStore(db)
mux := http.NewServeMux()
mux.HandleFunc("POST /api/bookmarks", handleCreateBookmark(store))
tests := []struct {
name string
body string
status int
}{
{"valid bookmark", `{"url":"https://go.dev","title":"Go"}`, http.StatusCreated},
{"missing url", `{"title":"No URL"}`, http.StatusBadRequest},
{"missing title", `{"url":"https://go.dev"}`, http.StatusBadRequest},
{"invalid json", `not json`, http.StatusBadRequest},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rec := doRequest(t, mux, "POST", "/api/bookmarks", tt.body)
assertStatus(t, rec.Code, tt.status)
})
}
}
func TestGetBookmark_NotFound(t *testing.T) {
db := setupTestDB(t)
store := NewBookmarkStore(db)
mux := http.NewServeMux()
mux.HandleFunc("GET /api/bookmarks/{id}", handleGetBookmark(store))
rec := doRequest(t, mux, "GET", "/api/bookmarks/9999", "")
assertStatus(t, rec.Code, http.StatusNotFound)
}Run with go test -v -run TestCreate.
⚠️ This test requires
setupTestDB, the store, and handler functions from the same package. SetTEST_DATABASE_URLto run database tests.