apitest

Getting started

Install apitest, write a first test, and read what a failure looks like.

Install

apitest requires Go 1.23 or later.

go get github.com/steinfletcher/apitest

apitest follows semantic versioning. Releases are published on GitHub.

Write a handler

Any http.Handler or handler function can be tested. This one greets the caller by name.

hello.go
func helloHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(map[string]string{
		"message": "hello " + r.URL.Query().Get("name"),
	})
}

Write a test

Pass the handler to apitest, describe the request, then call Expect(t) and describe the response you expect. End() runs the test.

hello_test.go
func TestHello(t *testing.T) {
	apitest.New().
		HandlerFunc(helloHandler).
		Get("/hello").
		Query("name", "gopher").
		Expect(t).
		Status(http.StatusOK).
		Header("Content-Type", "application/json").
		Body(`{"message": "hello gopher"}`).
		End()
}

No server is started. apitest calls the handler's ServeHTTP method directly with an httptest.ResponseRecorder, so tests are fast and need no free ports.

Run it

go test ./...

Reading a failure

apitest checks every expectation and reports all failures, not just the first. Suppose the test above expected 201 Created and the body {"message": "hello world"}. The output names each mismatch:

go test output
--- FAIL: TestHello (0.00s)
    assert.go:105:
        	Error Trace:	hello_test.go:18
        	Error:      	Not equal:
        	            	expected: 201
        	            	actual  : 200
        	Test:       	TestHello
        	Messages:   	Status code 200 not equal to 201
    assert.go:105:
        	Error Trace:	hello_test.go:18
        	Error:      	Not equal:
        	            	expected: map[string]interface {}{"message":"hello world"}
        	            	actual  : map[string]interface {}{"message":"hello gopher"}

        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,4 +1,4 @@
        	            	 (map[string]interface {}) (len=1) {
        	            	- (string) (len=7) "message": (string) (len=11) "hello world"
        	            	+ (string) (len=7) "message": (string) (len=12) "hello gopher"
        	            	 }
        	Test:       	TestHello

The body was compared as JSON, so the diff shows the decoded values rather than raw strings. Key order and whitespace never cause a failure.

Next steps

On this page