httpmock

package module
v0.1.13 Latest Latest
Warning

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

Go to latest
Published: May 26, 2023 License: MIT Imports: 17 Imported by: 3

README

httpmock

Build Status Coverage Status GoDevDoc Time Tracker Code lines Comments

HTTP Server and Client mocks for Go.

Example

// Prepare server mock.
sm, url := httpmock.NewServer()
defer sm.Close()

// This example shows Client and Server working together for sake of portability.
// In real-world scenarios Client would complement real server or Server would complement real HTTP client.

// Set successful expectation for first request out of concurrent batch.
exp := httpmock.Expectation{
    Method:     http.MethodPost,
    RequestURI: "/foo?q=1",
    RequestHeader: map[string]string{
        "X-Custom":     "def",
        "X-Header":     "abc",
        "Content-Type": "application/json",
    },
    RequestBody:  []byte(`{"foo":"bar"}`),
    Status:       http.StatusAccepted,
    ResponseBody: []byte(`{"bar":"foo"}`),
}
sm.Expect(exp)

// Set failing expectation for other requests of concurrent batch.
exp.Status = http.StatusConflict
exp.ResponseBody = []byte(`{"error":"conflict"}`)
exp.Unlimited = true
sm.Expect(exp)

// Prepare client request.
c := httpmock.NewClient(url)
c.ConcurrencyLevel = 50
c.Headers = map[string]string{
    "X-Header": "abc",
}

c.Reset().
    WithMethod(http.MethodPost).
    WithHeader("X-Custom", "def").
    WithContentType("application/json").
    WithBody([]byte(`{"foo":"bar"}`)).
    WithURI("/foo?q=1").
    Concurrently()

// Check expectations errors.
fmt.Println(
    c.ExpectResponseStatus(http.StatusAccepted),
    c.ExpectResponseBody([]byte(`{"bar":"foo"}`)),
    c.ExpectOtherResponsesStatus(http.StatusConflict),
    c.ExpectOtherResponsesBody([]byte(`{"error":"conflict"}`)),
)

// Output:
// <nil> <nil> <nil> <nil>

Documentation

Overview

Package httpmock provides utilities to test HTTP REST API.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	ConcurrencyLevel int
	JSONComparer     assertjson.Comparer
	OnBodyMismatch   func(received []byte) // Optional, called when received body does not match expected.
	Transport        http.RoundTripper

	// Headers are default headers added to all requests, can be overridden by WithHeader.
	Headers map[string]string

	// Cookies are default cookies added to all requests, can be overridden by WithCookie.
	Cookies map[string]string
	// contains filtered or unexported fields
}

Client keeps state of expectations.

func NewClient

func NewClient(baseURL string) *Client

NewClient creates client instance, baseURL may be empty if Client.SetBaseURL is used later.

Example
package main

import (
	"fmt"
	"net/http"

	"github.com/bool64/httpmock"
)

func main() {
	// Prepare server mock.
	sm, url := httpmock.NewServer()
	defer sm.Close()

	// This example shows Client and Server working together for sake of portability.
	// In real-world scenarios Client would complement real server or Server would complement real HTTP client.

	// Set successful expectation for first request out of concurrent batch.
	exp := httpmock.Expectation{
		Method:     http.MethodPost,
		RequestURI: "/foo?q=1",
		RequestHeader: map[string]string{
			"X-Custom":     "def",
			"X-Header":     "abc",
			"Content-Type": "application/json",
		},
		RequestBody:  []byte(`{"foo":"bar"}`),
		Status:       http.StatusAccepted,
		ResponseBody: []byte(`{"bar":"foo"}`),
	}
	sm.Expect(exp)

	// Set failing expectation for other requests of concurrent batch.
	exp.Status = http.StatusConflict
	exp.ResponseBody = []byte(`{"error":"conflict"}`)
	exp.Unlimited = true
	sm.Expect(exp)

	// Prepare client request.
	c := httpmock.NewClient(url)
	c.ConcurrencyLevel = 50
	c.Headers = map[string]string{
		"X-Header": "abc",
	}

	c.Reset().
		WithMethod(http.MethodPost).
		WithHeader("X-Custom", "def").
		WithContentType("application/json").
		WithBody([]byte(`{"foo":"bar"}`)).
		WithURI("/foo?q=1").
		Concurrently()

	// Check expectations errors.
	fmt.Println(
		c.ExpectResponseStatus(http.StatusAccepted),
		c.ExpectResponseBody([]byte(`{"bar":"foo"}`)),
		c.ExpectOtherResponsesStatus(http.StatusConflict),
		c.ExpectOtherResponsesBody([]byte(`{"error":"conflict"}`)),
	)

}
Output:

<nil> <nil> <nil> <nil>

func (*Client) AllowRetries added in v0.1.13

func (c *Client) AllowRetries(b RetryBackOff) *Client

AllowRetries allows sending multiple requests until first response assertion passes.

func (*Client) CheckUnexpectedOtherResponses

func (c *Client) CheckUnexpectedOtherResponses() error

CheckUnexpectedOtherResponses fails if other responses were present, but not expected with ExpectOther* functions.

Does not affect single (non-concurrent) calls.

func (*Client) Concurrently

func (c *Client) Concurrently() *Client

Concurrently enables concurrent calls to idempotent endpoint.

func (*Client) ExpectNoOtherResponses

func (c *Client) ExpectNoOtherResponses() error

ExpectNoOtherResponses sets expectation for only one response status to be received during concurrent calling.

Does not affect single (non-concurrent) calls.

func (*Client) ExpectOtherResponsesBody

func (c *Client) ExpectOtherResponsesBody(body []byte) error

ExpectOtherResponsesBody sets expectation for response body to be received one or more times during concurrent calling.

For example, it may describe "Not Found" response on multiple DELETE or "Conflict" response on multiple POST. Does not affect single (non-concurrent) calls.

func (*Client) ExpectOtherResponsesBodyCallback added in v0.1.9

func (c *Client) ExpectOtherResponsesBodyCallback(cb func(received []byte) error) error

ExpectOtherResponsesBodyCallback sets expectation for response body to be received one or more times during concurrent calling.

For example, it may describe "Not Found" response on multiple DELETE or "Conflict" response on multiple POST. Does not affect single (non-concurrent) calls.

func (*Client) ExpectOtherResponsesHeader

func (c *Client) ExpectOtherResponsesHeader(key, value string) error

ExpectOtherResponsesHeader sets expectation for response header value to be received one or more times during concurrent calling.

func (*Client) ExpectOtherResponsesStatus

func (c *Client) ExpectOtherResponsesStatus(statusCode int) error

ExpectOtherResponsesStatus sets expectation for response status to be received one or more times during concurrent calling.

For example, it may describe "Not Found" response on multiple DELETE or "Conflict" response on multiple POST. Does not affect single (non-concurrent) calls.

func (*Client) ExpectResponseBody

func (c *Client) ExpectResponseBody(body []byte) error

ExpectResponseBody sets expectation for response body to be received.

In concurrent mode such response must be met only once or for all calls.

func (*Client) ExpectResponseBodyCallback added in v0.1.9

func (c *Client) ExpectResponseBodyCallback(cb func(received []byte) error) error

ExpectResponseBodyCallback sets expectation for response body to be received as JSON payload.

In concurrent mode such response must be met only once or for all calls.

func (*Client) ExpectResponseHeader

func (c *Client) ExpectResponseHeader(key, value string) error

ExpectResponseHeader asserts expected response header value.

func (*Client) ExpectResponseStatus

func (c *Client) ExpectResponseStatus(statusCode int) error

ExpectResponseStatus sets expected response status code.

func (*Client) FollowRedirects added in v0.1.3

func (c *Client) FollowRedirects() *Client

FollowRedirects enables automatic following of Location header.

func (*Client) Fork added in v0.1.11

func (c *Client) Fork(ctx context.Context) (context.Context, *Client)

Fork checks ctx for an existing clone of this Client. If one is found, it is returned together with unmodified context. Otherwise, a clone of Client is created and put into a new derived context, then both new context and cloned Client are returned.

This method enables context-driven concurrent access to shared base Client.

func (*Client) Reset

func (c *Client) Reset() *Client

Reset deletes client state.

func (*Client) SetBaseURL

func (c *Client) SetBaseURL(baseURL string)

SetBaseURL changes baseURL configured with constructor.

func (*Client) WithBody

func (c *Client) WithBody(body []byte) *Client

WithBody sets request body.

func (*Client) WithContentType

func (c *Client) WithContentType(contentType string) *Client

WithContentType sets request content type.

func (*Client) WithContext added in v0.1.3

func (c *Client) WithContext(ctx context.Context) *Client

WithContext adds context to request.

func (*Client) WithCookie

func (c *Client) WithCookie(name, value string) *Client

WithCookie sets request cookie.

func (*Client) WithHeader

func (c *Client) WithHeader(key, value string) *Client

WithHeader sets request header.

func (*Client) WithMethod

func (c *Client) WithMethod(method string) *Client

WithMethod sets request HTTP method.

func (*Client) WithPath deprecated

func (c *Client) WithPath(path string) *Client

WithPath sets request URI path.

Deprecated: use WithURI.

func (*Client) WithQueryParam added in v0.1.5

func (c *Client) WithQueryParam(name, value string) *Client

WithQueryParam appends request query parameter.

func (*Client) WithURI

func (c *Client) WithURI(uri string) *Client

WithURI sets request URI.

func (*Client) WithURLEncodedFormDataParam added in v0.1.5

func (c *Client) WithURLEncodedFormDataParam(name, value string) *Client

WithURLEncodedFormDataParam appends request form data parameter.

type Expectation

type Expectation struct {
	Method        string
	RequestURI    string
	RequestHeader map[string]string
	RequestCookie map[string]string
	RequestBody   []byte

	Status         int
	ResponseHeader map[string]string
	ResponseBody   []byte

	// Unlimited enables reusing of this expectation unlimited number of times.
	Unlimited bool
	// Repeated defines how many times this expectation should be used.
	Repeated int
}

Expectation describes expected request and defines response.

type RetryBackOff added in v0.1.13

type RetryBackOff interface {
	// NextBackOff returns the duration to wait before retrying the operation,
	// or -1 to indicate that no more retries should be made.
	//
	// Example usage:
	//
	// 	duration := retryBackOff.NextBackOff();
	// 	if (duration == retryBackOff.Stop) {
	// 		// Do not retry operation.
	// 	} else {
	// 		// Sleep for duration and retry operation.
	// 	}
	//
	NextBackOff() time.Duration
}

RetryBackOff defines retry strategy.

This interface matches github.com/cenkalti/retryBackOff/v4.BackOff.

type RetryBackOffFunc added in v0.1.13

type RetryBackOffFunc func() time.Duration

RetryBackOffFunc implements RetryBackOff with a function.

func (RetryBackOffFunc) NextBackOff added in v0.1.13

func (r RetryBackOffFunc) NextBackOff() time.Duration

NextBackOff returns the duration to wait before retrying the operation, or -1 to indicate that no more retries should be made.

type Server

type Server struct {
	// OnError is called on expectations mismatch or internal errors, optional.
	OnError func(err error)

	// OnRequest is called on before every request, optional.
	OnRequest func(rw http.ResponseWriter, req *http.Request)

	// ErrorResponder allows custom failure responses.
	ErrorResponder func(rw http.ResponseWriter, err error)

	// DefaultResponseHeaders are added to every response to an expected request.
	DefaultResponseHeaders map[string]string

	// JSONComparer controls JSON equality check.
	JSONComparer assertjson.Comparer

	// OnBodyMismatch is called when received body does not match expected, optional.
	OnBodyMismatch func(received []byte)
	// contains filtered or unexported fields
}

Server serves predefined response for predefined request.

func NewServer

func NewServer() (*Server, string)

NewServer creates mocked server.

func (*Server) Close

func (sm *Server) Close()

Close closes mocked server.

func (*Server) Expect

func (sm *Server) Expect(e Expectation)

Expect adds expected operation.

func (*Server) ExpectAsync

func (sm *Server) ExpectAsync(e Expectation)

ExpectAsync sets non-sequential expectation.

Asynchronous expectations are checked for every incoming request, first match is used for response. If there are no matches, regular (sequential expectations are used).

func (*Server) ExpectationsWereMet

func (sm *Server) ExpectationsWereMet() error

ExpectationsWereMet checks whether all queued expectations were met in order. If any of them was not met - an error is returned.

func (*Server) ResetExpectations

func (sm *Server) ResetExpectations()

ResetExpectations discards all expectation to reset the state of mock.

func (*Server) ServeHTTP

func (sm *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP asserts request expectations and serves mocked response.

Jump to

Keyboard shortcuts

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