v1.8 · Go 1.23+ · zero dependencies

Behavioural tests for Go HTTP services

Build a request, send it to your handler, and assert on the response. Mock the services it calls, and get a sequence diagram of every test.

$go get github.com/steinfletcher/apitest

How it reads

One readable chain per test

Everything before Expect describes the request. Everything after it describes the response. 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()
}

Every sample on this site is included from tests that run against the latest release.

Features

Everything a handler test needs

apitest covers the whole path of a request through your service, without asking you to change how it is built.

Reads like the request it makes

One fluent chain describes the request and the response you expect. No setup boilerplate, no servers, no ports.

Mock the services you call

Declarative mocks answer outbound HTTP calls, with matchers for paths, headers, query, body, cookies and more.

A diagram of every test

Render each test as a sequence diagram of the request, mocked calls, database queries and the response.

Any http.Handler

Works with net/http, chi, gin, echo, gorilla and anything else that serves HTTP, or a server over the network.

Zero dependencies

The core library depends only on the standard library. Extras such as JSONPath live in separate modules.

Extensible at every step

Custom assertions, mock matchers, verifiers, observers and report formatters are all plain Go functions and interfaces.

Anatomy of a test

Configure, request, expect

Every test has the same three parts, so a whole suite reads consistently.

  1. 1

    Configuration

    The handler under test, mocks for the services it calls, and options such as reporting and debug output.

  2. 2

    Request

    The method, URL, headers, query, cookies and body, built with a fluent API.

  3. 3

    Expectations

    The status, headers, cookies and body you expect, plus any custom assertions.

Read about the anatomy of a test
user_test.go
func TestGetUser(t *testing.T) {
	apitest.New("gets a user").
		// 1. configuration
		Mocks(getUserMock, getPreferencesMock).
		Handler(newUserAPI()).
		// 2. request
		Get("/user/1234").
		// 3. expectations
		Expect(t).
		Status(http.StatusOK).
		Body(`{"id": "1234", "name": "jon", "is_contactable": true}`).
		End()
}

Reports

See what your service actually did

Add one line to a test and apitest writes a self-contained HTML report: an interactive sequence diagram of every interaction, the wire log of each message, and a flag on any call that matched no mock. Database queries and your own events can be drawn too.

An apitest report for GET /user/1234, with a sequence diagram of the calls to the users and preferences services and the list of messages

Works with

Bring your own stack

If it serves HTTP in Go, apitest can test it.

  • net/http
  • chi
  • gin
  • echo
  • gorilla/mux
  • httprouter
  • iris
  • fiber
  • gqlgen
  • Ginkgo
  • database/sql

Framework guides

Write your first test in a minute

Install the module, point it at a handler, and describe what should happen.

$go get github.com/steinfletcher/apitest
Read the guide