Basic Handler Testing

Testing HTTP handlers is an essential part of building reliable REST APIs. Go's standard library provides the httptest package, which makes testing HTTP handlers straightforward without requiring a running server.

The httptest Package

The httptest package offers tools to simulate HTTP requests and record responses for verification:

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

Testing a Simple Handler

Let's test our basic "Hello world" handler:

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestHandler(t *testing.T) {
	// Create a request to pass to our handler
	req, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatal(err)
	}

	// Create a ResponseRecorder to record the response
	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(handler)

	// Call the handler directly, passing in the request and response recorder
	handler.ServeHTTP(rr, req)

	// Check the status code
	if status := rr.Code; status != http.StatusOK {
		t.Errorf("handler returned wrong status code: got %v want %v",
			status, http.StatusOK)
	}

	// Check the response body
	expected := "Hello world"
	if rr.Body.String() != expected {
		t.Errorf("handler returned unexpected body: got %v want %v",
			rr.Body.String(), expected)
	}
}

From within the goexamples/example-helloworld run:

go test -v ./...

output:

=== RUN   TestHandler
--- PASS: TestHandler (0.00s)
PASS
ok      goexamples/helloworld   0.003s

Best Practices

When writing handler tests:

  1. Test status codes: Verify your handler returns the expected HTTP status codes
  2. Test response headers: Check for expected headers like Content-Type
  3. Test response body: Validate the content of the response
  4. Test error cases: Ensure handlers respond appropriately to invalid inputs
  5. Keep tests focused: Each test should verify one specific aspect of the handler