Go in Practice 10. Testing Example

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. Set TEST_DATABASE_URL to run database tests.

💻 Run locally

Copy the code above and run it on your machine

© 2026 ByteLearn.dev. Free courses for developers. · Privacy