gomockserver

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2021 License: MIT Imports: 8 Imported by: 0

README

Go Mock Server

CI GoDoc Coverage Status Go Report Card license

Provide a way to mock out an HTTP Server for testing purposes, to ensure that calls are made correctly and return appropriate responses.

Usage

Firstly a new mock server instance is needed:

server := gomockserver.New(t)
defer server.Close()

Closing the server is important, and should be done once it's no longer needed. The defer ensures this happens at the end of the current test.

Once created, the server will handle all incoming requests to it. The URL can be determined by using server.URL(), which will return a string like http://127.0.0.1:54681. This is the base URL to the server, under which all requests can be handled.

Once set up, the server can be configured to match incoming requests and return responses to them. For example, the following will handle a call to GET /testing/abc and return an application/json response with a body of "Hello":

server.Matches(gomockserver.MatchRequest("GET", "/testing/abc")).
	RespondsWith(gomockserver.ResponseJSON("Hello"))
Matches

The call to server.Matches() will take a number of MatchRule instances. A Match is considered successful if every single MatchRule passes for the incoming request. This allows requests to match against as many or as few details as possible.

Standard rules that can be configured are:

  • MatchMethod - Matches the HTTP Method
  • MatchURLPath - Matches the full incoming URL
  • MatchURLQuery - Matches a query parameter with a specific value
  • MatchRequest - Matches both the HTTP Method and the URL
  • MatchHeader - Matches a header name with a specific value
  • MatchJSONFull - Matches the request body in full against a JSON document
  • MatchJSONCompatible - Ensures the request body is a superset of a given JSON document - i.e. additional fields in the request do not stop this from matching.

Both MathJSONFull and MatchJSONCompatible take interface{}, and this will be marshalled into a JSON document before matching. This allows any Go constructs that marshal into JSON to be used - e.g., map[string]interface{} or your own custom structs.

Additionally, you can write any custom match rule that you want as long as it fulfils the MatchRule interface. There is also a MatchRuleFunc function type that already implements the interface, so rules can be written as anonymous functions if desired.

Responses

The result of calling server.Matches() is a *Match. This can then be augmented to detail how the response should look, by adding ResponseBuilder instances via the RespondWith method. As with Matches(), this method can take as many ResponseBuilder instances as needed, each of which will configure the response in some manner.

Standard response builders that can be configured are:

  • ResponseStatus - Sets the status code
  • ResponseSetHeader - Overwrites a response header
  • ResponseAppendHeader - Append a new value to a response header
  • ResponseBody - Set the body of the response
  • ResponseJSON - Set the body of the response to the JSON encoding of the provided object, and set the Content-Type header to application/json.

Additionally, you can write any custom builder that you want as long as it fulfils the ResponseBuilder interface. There is also a ResponseBuilderFunc function type that already implements the interface, so rules can be written as anonymous functions if desired.

Matching Requests

Every request that is received by the mock server is compared to every Match that is configured, in the order they were configured, until the first one is a match. At this point,the response from this Match is built and sent back to the client.

You can configure as many different Matches on the server as you want, but every request will only ever match at most one.

Any incoming requests that do not match a configured Match will return an HTTP 404 Not Found.

Counting Requests

Go Mock Server will keep track of the number of times every Match has been used to respond to a request. This can be used in tests to assert that a given request was made the correct number of times:

match := server.Matches(gomockserver.MatchRequest("GET", "/testing/abc")).
	RespondsWith(gomockserver.ResponseJSON("Hello"))

// Run tests

is.Equal(match.Count(), 1)

We also keep track of the number of times we handled unmatched requests, in case that's interesting. Most often that will be used to assert that this was zero - i.e. that all the requests that we handled were matched:

// Run tsts

is.Equal(server.UnmatchedCount(), 0)

Examples

Examples of how to use this can be found in server_test.go.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Match

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

Match represents a matching in the mock server to potentially handle incoming requests.

func (*Match) Count added in v0.1.1

func (m *Match) Count() int

Count will return the number of times this match has been used to respond to a request.

func (*Match) Matches

func (m *Match) Matches(r *http.Request) bool

Matches will check if every rule in this `Match` passes for the incoming request.

func (*Match) RespondsWith

func (m *Match) RespondsWith(builders ...ResponseBuilder) *Match

RespondsWith registers new response builders to use to build the response to an incoming request.

type MatchRule

type MatchRule interface {
	// Matches will check to see if the provided HTTP request matches this rule.
	Matches(r *http.Request) bool
}

MatchRule represents a rule to match against to see if a request should be processed.

func MatchHeader

func MatchHeader(name, value string) MatchRule

MatchHeader builds a `MatchRule` to check if the given header is present and has the given value. If the header is repeated then only one of the repeated values needs to have the provided value.

func MatchJSONCompatible

func MatchJSONCompatible(expected interface{}) MatchRule

MatchJSONCompatible will compare the request body to the provided JSON string and ensure that the two are compatible. Every value in the request body must be present in the expected body, but the request body may contain keys that are not present in the expected body as well.

For example, the following is a valid match: * Request Body = {"a": 1, "b": {"c": 2, "d": 3}, "e": 4} * Expected = {"a": 1, "b": {"c": 2}}

As with MatchJSONFull, the order of keys is not important.

func MatchJSONFull

func MatchJSONFull(expected interface{}) MatchRule

MatchJSONFull will compare the request body to the provided JSON string and ensure that the two are semantically identical. The order of keys in JSON objects is not important, but every value must be present.

func MatchMethod

func MatchMethod(method string) MatchRule

MatchMethod builds a `MatchRule` to check if the HTTP Method of the request matches the one provided.

func MatchRequest

func MatchRequest(method, url string) MatchRule

MatchRequest is a helper that matches both the HTTP Method and URL of the request.

func MatchURLPath added in v0.1.1

func MatchURLPath(expected string) MatchRule

MatchURLPath builds a `MatchRule` to check if the URL Path of the request matches the one provided. Note that this does a complete match, not a partial one.

func MatchURLQuery added in v0.1.1

func MatchURLQuery(name, value string) MatchRule

MatchURLQuery builds a `MatchRule` to check if a query parameter is present with the given name and value. If the query parameter is repeated then only one of the repeated values needs to have the provided value.

type MatchRuleFunc

type MatchRuleFunc func(*http.Request) bool

MatchRuleFunc is a function type that implements the `MatchRule` interface. This allows for simple functions to be used in place of the interface.

func (MatchRuleFunc) Matches

func (m MatchRuleFunc) Matches(r *http.Request) bool

type MatchRules

type MatchRules []MatchRule

MatchRules is a type representing a slice of `MatchRule`. This allows for multiple rules to be treated as a single rule.

func (MatchRules) Matches

func (m MatchRules) Matches(r *http.Request) bool

type Mock added in v0.1.3

type Mock struct {
	Matches  []MatchRule
	Response []ResponseBuilder
}

Mock represents a lightweight representation of a mock to add to the server.

func NewMock added in v0.1.3

func NewMock(params ...interface{}) Mock

NewMock will create a new Mock instance from an assortment of MatchRule and ResponseBuilder types.

type MockServer

type MockServer interface {
	// Close will shut the mock server down. This must always be called, preferably via `defer`.
	Close()
	// URL will generate a URL representing the mock server. This includes the scheme, host and post of the server.
	URL() string
	// Matches will record a new match against the server that will potentially process any incoming requests.
	Matches(...MatchRule) *Match
	// Mount will create a new
	Mount(Mock) *Match
	// UnmatchedCount will return the number of times a request has been handmed and not matched.
	UnmatchedCount() int
}

MockServer represents the actual server that will be used in the tests.

func New

func New(t *testing.T) MockServer

New will create a new mock server ready for use in tests.

type Response

type Response struct {
	Status  int
	Headers http.Header
	Body    []byte
}

Response is a representation of the response to send to the client.

func (Response) Write

func (r Response) Write(w http.ResponseWriter)

Write will write the response details to the provided response writer.

type ResponseBuilder

type ResponseBuilder interface {
	// PopulateResponse is called to allow the builder to update any parts of the response struct.
	PopulateResponse(r *Response, req *http.Request)
}

ResponseBuilder is a means to contribute to the response to send to the client.

func ResponseAppendHeader

func ResponseAppendHeader(name, value string) ResponseBuilder

ResponseAppendHeader will append a new value for the header name provided.

func ResponseBody

func ResponseBody(data []byte) ResponseBuilder

ResponseBody will indicate the data to return as the response body.

func ResponseJSON

func ResponseJSON(data interface{}) ResponseBuilder

ResponseJSON will encode the provided value as JSON and use it as the response, also setting the content-type header.

func ResponseSetHeader

func ResponseSetHeader(name, value string) ResponseBuilder

ResponseSetHeader will set a header value to exactly the value provided.

func ResponseStatus

func ResponseStatus(status int) ResponseBuilder

ResponseStatus returns a `ResponseBuilder` to specify the status code of the response.

type ResponseBuilderFunc

type ResponseBuilderFunc func(*Response, *http.Request)

ResponseBuilderFunc is function type that implements the `ResponseBuilder` interface.

func (ResponseBuilderFunc) PopulateResponse

func (f ResponseBuilderFunc) PopulateResponse(r *Response, req *http.Request)

type ResponseBuilders

type ResponseBuilders []ResponseBuilder

ResponseBuilders represents a set of builders that are all called in sequence to populate a response.

func (ResponseBuilders) PopulateResponse

func (b ResponseBuilders) PopulateResponse(r *Response, req *http.Request)

Jump to

Keyboard shortcuts

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