apitest

Web frameworks

Test handlers built with chi, gin, echo, gorilla, fiber and other Go web frameworks.

apitest accepts any http.Handler. The routers of most Go web frameworks implement it, so you pass the router to Handler, exactly as you would to http.ListenAndServe. Testing through the router also exercises your routes, path parameters and middleware.

Go 1.22 and later support methods and path parameters in http.ServeMux patterns:

type User struct {
	ID            string `json:"id,omitempty"`
	Name          string `json:"name"`
	IsContactable bool   `json:"is_contactable"`
}

func newUserAPI() http.Handler {
	mux := http.NewServeMux()

	mux.HandleFunc("GET /user/{id}", func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")

		var user User
		if err := getJSON(r.Context(), "http://users/api/user/"+id, &user); err != nil {
			writeError(w, err)
			return
		}

		var prefs struct {
			IsContactable bool `json:"is_contactable"`
		}
		if err := getJSON(r.Context(), "http://preferences/api/preferences/"+id, &prefs); err != nil {
			writeError(w, err)
			return
		}

		user.IsContactable = prefs.IsContactable
		writeJSON(w, http.StatusOK, user)
	})

	mux.HandleFunc("POST /user", func(w http.ResponseWriter, r *http.Request) {
		var user User
		if err := json.NewDecoder(r.Body).Decode(&user); err != nil || user.Name == "" {
			writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name is required"})
			return
		}

		var created User
		if err := postJSON(r.Context(), "http://users/api/user", user, &created); err != nil {
			writeError(w, err)
			return
		}
		writeJSON(w, http.StatusCreated, created)
	})

	return mux
}
apitest.Handler(newUserAPI()).
	Get("/user/1234").
	Expect(t).
	Status(http.StatusOK).
	End()

Other frameworks

FrameworkHow to test it
gorilla/mux*mux.Router implements http.Handler.
httprouter*httprouter.Router implements http.Handler.
irisCall app.Build(), then pass app.Router.
fiberfiber is built on fasthttp, not net/http. Adapt it with a handler function that calls app.Test(r) and copies the response, as in the linked example.
GraphQL with gqlgenThe gqlgen server is an http.Handler.
WebSocketsTest the upgrade handshake and HTTP endpoints of a websocket handler.

Middleware

Pass the handler with its middleware applied to test the stack your users hit, or the bare handler to test it in isolation. When a handler expects values that middleware adds to the request context, such as an authenticated user, set them with WithContext.

On this page