httpclienttest

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2025 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package httpclienttest provides testing utilities for HTTP client code.

Makes testing HTTP interactions easier, more reliable, and less dependent on external services. Follows common testing patterns like spies, stubs, and mocks for unit test verification.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DoerSpy

type DoerSpy struct {
	// contains filtered or unexported fields
}

DoerSpy implements httpclient.Doer and records all calls to the underlying Doer. Useful for verifying specific HTTP requests were made. Safe for concurrent use.

func NewDoerSpy

func NewDoerSpy(doer httpclient.Doer) *DoerSpy

NewDoerSpy creates DoerSpy wrapping the provided Doer. Forwards all requests while recording inputs and outputs for inspection.

func (*DoerSpy) Calls

func (d *DoerSpy) Calls() []DoerSpyRecord

Calls returns a copy of all recorded calls made through this spy and clears the internal call history. Each call returns a fresh slice, making it safe to call concurrently. The returned slice contains calls in the order they were made.

func (*DoerSpy) Do

func (d *DoerSpy) Do(req *http.Request) (*http.Response, error)

Do implements httpclient.Doer by forwarding the request to the wrapped Doer and recording both the input request and output response/error for later retrieval. This method is safe for concurrent use.

type DoerSpyRecord

type DoerSpyRecord struct {
	InputRequest   *http.Request
	OutputResponse *http.Response
	OutputError    error
}

DoerSpyRecord represents a single recorded HTTP request/response interaction. It captures the complete input and output of one call to the Do method, including any error that may have occurred during the request.

type DoerStub

type DoerStub struct {
	// contains filtered or unexported fields
}

DoerStub implements httpclient.Doer and returns pre-configured responses without making actual HTTP requests. Useful for controlling exact responses or testing error conditions.

Two modes: strict order (exact consumption order) or flexible order (first match). Safe for concurrent use.

func NewDoerStub

func NewDoerStub(calls []DoerStubCall, strictOrder bool) *DoerStub

NewDoerStub creates DoerStub with provided call configurations. Calls slice defines responses for matching requests.

If strictOrder is true, calls consumed in exact order, non-matches error. If false, first matching call (or no matcher) used and consumed. See DoerStubCall for configuring individual responses.

func (*DoerStub) Do

func (d *DoerStub) Do(req *http.Request) (*http.Response, error)

Do implements httpclient.Doer by returning pre-configured responses based on the configured DoerStubCall slice. The behavior depends on the strictOrder setting:

In strict order mode (strictOrder=true):

  • calls are processed in the exact order they were configured
  • if a call has a RequestMatcher and the request doesn't match, an error is returned
  • if a call has no RequestMatcher, it matches any request

In flexible order mode (strictOrder=false):

  • calls are searched in order until a matching one is found
  • non-matching calls are skipped
  • the first matching call (or call without a matcher) is used and consumed

Returns an error if no configured calls remain or if no call matches the request. This method is safe for concurrent use.

func (*DoerStub) RemainingCalls

func (d *DoerStub) RemainingCalls() []DoerStubCall

RemainingCalls returns a copy of all DoerStubCall configurations that have not yet been consumed by calls to Do. This is useful in tests to verify that all expected HTTP calls were actually made. The returned slice is a copy and safe to modify. This method is safe for concurrent use.

type DoerStubCall

type DoerStubCall struct {
	Matcher RequestMatcher

	Response *http.Response
	Error    error
}

DoerStubCall defines the configuration for a single stubbed HTTP call. It consists of an optional RequestMatcher to determine if an incoming request should use this configuration, and a Response/Error pair to return.

If Matcher is nil, this call configuration will match any request. If Matcher is set, the incoming request must pass all the matcher's assertions for this configuration to be used.

type RequestMatcher

type RequestMatcher interface {
	MatchRequest(req *http.Request) error
}

RequestMatcher defines an interface for validating HTTP requests against predefined criteria. Implementations should return nil if the request matches all expected conditions, or a descriptive error if any condition fails. This interface is commonly used with DoerStub to ensure that stubbed responses are only returned for expected requests.

type RequestMatcherBuilder

type RequestMatcherBuilder struct {
	// contains filtered or unexported fields
}

RequestMatcherBuilder provides a fluent interface for building complex HTTP request assertions. It implements the RequestMatcher interface and allows chaining multiple validation criteria such as HTTP method, URL components, headers, and body content. Each method adds a new assertion that will be checked when MatchRequest is called.

func NewRequestMatcherBuilder

func NewRequestMatcherBuilder() *RequestMatcherBuilder

NewRequestMatcherBuilder creates a new empty RequestMatcherBuilder with no assertions. Use the builder's methods to add specific validation criteria for HTTP requests.

func (*RequestMatcherBuilder) BodyForm

func (b *RequestMatcherBuilder) BodyForm(compareWith url.Values, strict bool) *RequestMatcherBuilder

BodyForm adds an assertion that the request body contains form data matching the provided url.Values. The request's Content-Type should be "application/x-www-form-urlencoded". If strict is true, the form data must match exactly with no additional fields. If strict is false, additional fields in the request are allowed.

func (*RequestMatcherBuilder) BodyJSON

func (b *RequestMatcherBuilder) BodyJSON(compareWith any, getDest func() any, strict bool) *RequestMatcherBuilder

BodyJSON adds an assertion that the request body contains JSON data that can be unmarshalled into the type returned by getDest() and matches compareWith exactly. The getDest function should return a new instance of the expected type for unmarshalling. If strict is true, the JSON must not contain any fields not present in the target type. If strict is false, additional JSON fields are ignored during unmarshalling.

func (*RequestMatcherBuilder) HeadersContains

func (b *RequestMatcherBuilder) HeadersContains(headers http.Header) *RequestMatcherBuilder

HeadersContains adds an assertion that the request headers must contain all the provided header key-value pairs. Additional headers in the request are allowed. Header names are case-insensitive, but values must match exactly including order.

func (*RequestMatcherBuilder) MatchRequest

func (b *RequestMatcherBuilder) MatchRequest(req *http.Request) error

MatchRequest implements the RequestMatcher interface by running all configured assertions against the provided HTTP request. It returns nil if all assertions pass, or a combined error containing details of all failed assertions.

func (*RequestMatcherBuilder) Method

Method adds an assertion that the HTTP request method must exactly match the provided method. The comparison is case-sensitive (e.g., "GET", "POST", "PUT").

func (*RequestMatcherBuilder) URLHost

URLHost adds an assertion that the request URL's host component must exactly match the provided host string. This includes the hostname and optional port (e.g., "example.com:8080").

func (*RequestMatcherBuilder) URLPath

URLPath adds an assertion that the request URL's path component must exactly match the provided path string. The path should include the leading slash (e.g., "/api/users").

func (*RequestMatcherBuilder) URLQueryParamsContains

func (b *RequestMatcherBuilder) URLQueryParamsContains(params url.Values) *RequestMatcherBuilder

URLQueryParamsContains adds an assertion that the request URL's query parameters must contain all the provided key-value pairs. Additional query parameters in the request are allowed. The values for each key must match exactly, including order.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server provides a testing utility that creates temporary HTTP servers for validating HTTP client behavior. It combines request assertion with response generation, allowing tests to verify that clients make expected requests and handle responses correctly. The server automatically starts and stops a httptest.Server for each assertion.

func NewServer

func NewServer(do func(serverAddress url.URL, serverDoer httpclient.Doer, checkResponseFunc any) error) *Server

NewServer creates a new Server with the provided request execution function. The do function should contain the code under test that makes HTTP requests. It receives the temporary server's URL, an HTTP client (typically httptest server's client), and an optional checkResponseFunc parameter that can be used for additional response validation. The do function should return an error if the HTTP request or response handling fails.

func (*Server) AssertRequest

func (srv *Server) AssertRequest(requestExpectations RequestMatcher, writeResponse func(http.ResponseWriter) error, checkResponseFunc any) error

AssertRequest creates a temporary HTTP server, executes the configured request function, and validates both the incoming request and outgoing response. It performs three main steps:

  1. creates a httptest.Server that validates incoming requests using requestExpectations
  2. calls the configured do function with the server URL and client
  3. uses writeResponse to generate the HTTP response sent back to the client

The requestExpectations RequestMatcher validates that the incoming HTTP request meets all specified criteria (method, headers, body, etc.).

The writeResponse function is responsible for writing the HTTP response, including status code, headers, and body. It should return an error if response writing fails.

The checkResponseFunc parameter is passed through to the do function and can be used for additional response validation logic specific to the test case.

Returns an error if request validation fails, response writing fails, or the do function returns an error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL