httpmock

package module
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2024 License: MIT Imports: 9 Imported by: 1

README

httpmock

GoDoc Go Report Card Build Status

This library builds on Go's built-in httptest library, adding a more mockable interface that can be used easily with other mocking tools like testify/mock. It does this by providing a Handler that receives HTTP components as separate arguments rather than a single *http.Request object.

Where the typical http.Handler interface is:

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

This library provides a server with the following interface, which works naturally with mocking libraries:

// Handler is the interface used by httpmock instead of http.Handler so that it can be mocked very easily.
type Handler interface {
	Handle(method, path string, body []byte) Response
}

Examples

The most primitive example, the OKHandler, just returns 200 OK to everything.

s := httpmock.NewServer(&httpmock.OKHandler{})
defer s.Close()

// Make any requests you want to s.URL(), using it as the mock downstream server

This example uses MockHandler, a Handler that is a testify/mock object.

downstream := httpmock.NewMockHandler(t)

// A simple GET that returns some pre-canned content
downstream.On("Handle", "GET", "/object/12345", mock.Anything).Return(httpmock.Response{
    Body: []byte(`{"status": "ok"}`),
})

s := httpmock.NewServer(downstream)
defer s.Close()

//
// Make any requests you want to s.URL(), using it as the mock downstream server
//

downstream.AssertExpectations(t)

If instead you wish to match against headers as well, a slightly different httpmock object can be used (please note the change in function name to be matched against):

downstream := &httpmock.NewMockHandlerWithHeaders(t)

// A simple GET that returns some pre-canned content and expects a specific header.
// Use MultiHeaderMatcher for multiple headers.
downstream.On("HandleWithHeaders", "GET", "/object/12345", HeaderMatcher("MOCK", "this"), mock.Anything).Return(httpmock.Response{
    Body: []byte(`{"status": "ok"}`),
})

// ... same as above

The httpmock package also provides helpers for checking calls using json objects, like so:

// This tests a hypothetical "echo" endpoint, which returns the body we pass to it.
type Obj struct {
    A string `json:"a"`
}

o := &Obj{A: "aye"}

// JSONMatcher ensures that this mock is triggered only when the HTTP body, when deserialized, matches the given
// object. Here, this mock response will get triggered only if `{"a":"aye"}` is sent.
downstream.On("Handle", "POST", "/echo", httpmock.JSONMatcher(o)).Return(httpmock.Response{
    Body: httpmock.ToJSON(o),
})

Documentation

Overview

Package httpmock builds on httptest, providing easier API mocking.

Essentially all httpmock does is implement a similar interface to httptest, but using a Handler that receives the HTTP method, path, and body rather than a request object. This makes it very easy to use a featureful mock as the handler, e.g. github.com/stretchr/testify/mock

Examples

s := httpmock.NewServer(&httpmock.OKHandler{})
defer s.Close()

// Make any requests you want to s.URL(), using it as the mock downstream server

This example uses MockHandler, a Handler that is a github.com/stretchr/testify/mock object.

downstream := httpmock.NewMockHandler(t)

// A simple GET that returns some pre-canned content
downstream.On("Handle", "GET", "/object/12345", mock.Anything).Return(httpmock.Response{
	Body: []byte(`{"status": "ok"}`),
})

s := httpmock.NewServer(downstream)
defer s.Close()

//
// Make any requests you want to s.URL(), using it as the mock downstream server
//

downstream.AssertExpectations(t)

If instead you wish to match against headers as well, a slightly different httpmock object can be used (please note the change in function name to be matched against):

downstream := httpmock.NewMockHandlerWithHeaders(t)

// A simple GET that returns some pre-canned content
downstream.On("HandleWithHeaders", "GET", "/object/12345", MatchHeader("MOCK", "this"), mock.Anything).Return(httpmock.Response{
    Body: []byte(`{"status": "ok"}`),
})

// ... same as above

Httpmock also provides helpers for checking calls using json objects, like so:

// This tests a hypothetical "echo" endpoint, which returns the body we pass to it.
type Obj struct {
	A string `json:"a"`
	B string `json:"b"`
}

o := &Obj{A: "ay", B: "bee"}

// JSONMatcher ensures that this mock is triggered only when the HTTP body, when deserialized, matches the given
// object.
downstream.On("Handle", "POST", "/echo", httpmock.JSONMatcher(o)).Return(httpmock.Response{
	Body: httpmock.ToJSON(o),
})

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HeaderMatcher added in v1.0.2

func HeaderMatcher(key, value string) interface{}

HeaderMatcher matches the presence of a header named key that has a given value. Other headers are allowed to exist and are not checked.

func JSONMatcher

func JSONMatcher(o1 interface{}) interface{}

JSONMatcher returns a mock.MatchedBy func to check if the argument is the json form of the provided object. See the github.com/stretchr/testify/mock documentation and example in httpmock.go.

func MultiHeaderMatcher added in v1.0.2

func MultiHeaderMatcher(desiredHeaders http.Header) interface{}

MultiHeaderMatcher matches the presence and content of multiple headers. Other headers besides those within desiredHeaders are allowed to exist and are not checked.

func ToJSON

func ToJSON(obj interface{}) []byte

ToJSON is a convenience function for converting an object to JSON inline. It panics on failure, so should be used only in test code.

Types

type Handler

type Handler interface {
	Handle(method, path string, body []byte) Response
}

Handler is the interface used by httpmock instead of http.Handler so that it can be mocked very easily.

type HandlerWithHeaders added in v1.0.2

type HandlerWithHeaders interface {
	Handler
	HandleWithHeaders(method, path string, headers http.Header, body []byte) Response
}

HandlerWithHeaders is the interface used by httpmock instead of http.Handler so that it can be mocked very easily, it additionally allows matching on headers.

type MockHandler

type MockHandler struct {
	mock.Mock
}

MockHandler is a httpmock.Handler that uses github.com/stretchr/testify/mock.

func NewMockHandler added in v1.0.3

func NewMockHandler(t *testing.T) *MockHandler

NewMockHandler returns a pointer to a new mock handler with the test struct set

func (*MockHandler) Handle

func (m *MockHandler) Handle(method, path string, body []byte) Response

Handle makes this implement the Handler interface.

type MockHandlerWithHeaders added in v1.0.2

type MockHandlerWithHeaders struct {
	mock.Mock
}

MockHandlerWithHeaders is a httpmock.Handler that uses github.com/stretchr/testify/mock.

func NewMockHandlerWithHeaders added in v1.0.3

func NewMockHandlerWithHeaders(t *testing.T) *MockHandlerWithHeaders

NewMockHandlerWithHeaders returns a pointer to a new mock handler with headers with the test struct set

func (*MockHandlerWithHeaders) Handle added in v1.0.2

func (m *MockHandlerWithHeaders) Handle(method, path string, body []byte) Response

Handle makes this implement the Handler interface.

func (*MockHandlerWithHeaders) HandleWithHeaders added in v1.0.2

func (m *MockHandlerWithHeaders) HandleWithHeaders(method, path string, headers http.Header, body []byte) Response

HandleWithHeaders makes this implement the HandlerWithHeaders interface.

type OKHandler

type OKHandler struct {
}

OKHandler is a simple Handler that returns 200 OK responses for any request.

func (*OKHandler) Handle

func (r *OKHandler) Handle(method, path string, body []byte) Response

Handle makes this implement the Handler interface.

type Response

type Response struct {
	// The HTTP status code to write (default: 200)
	Status int
	// Headers to add to the response
	Header http.Header
	// The response body to write (default: no body)
	Body []byte
}

Response holds the response a handler wants to return to the client.

type Server

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

Server listens for requests and interprets them into calls to your Handler.

func NewServer

func NewServer(handler Handler) *Server

NewServer constructs a new server and starts it (compare to httptest.NewServer). It needs to be Closed()ed. If you pass a handler that conforms to the HandlerWithHeaders interface, when requests are received, the HandleWithHeaders method will be called rather than Handle.

func NewUnstartedServer

func NewUnstartedServer(handler Handler) *Server

NewUnstartedServer constructs a new server but doesn't start it (compare to httptest.NewUnstartedServer). If you pass a handler that conforms to the HandlerWithHeaders interface, when requests are received, the HandleWithHeaders method will be called rather than Handle.

func (*Server) Close

func (s *Server) Close()

Close shuts down a started server.

func (*Server) Start

func (s *Server) Start()

Start starts an unstarted server.

func (*Server) URL

func (s *Server) URL() string

URL is the URL for the local test server, i.e. the value of httptest.Server.URL

Jump to

Keyboard shortcuts

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