Provide a way to mock out an HTTP Server for testing purposes, to ensure that calls are made correctly and return appropriate responses.
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"))
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 MethodMatchURLPath
- Matches the full incoming URLMatchURLQuery
- Matches a query parameter with a specific valueMatchRequest
- Matches both the HTTP Method and the URLMatchHeader
- Matches a header name with a specific valueMatchJSONFull
- Matches the request body in full against a JSON documentMatchJSONCompatible
- 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.
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 codeResponseSetHeader
- Overwrites a response headerResponseAppendHeader
- Append a new value to a response headerResponseBody
- Set the body of the responseResponseJSON
- Set the body of the response to the JSON encoding of the provided object, and set theContent-Type
header toapplication/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.
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 Match
es 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
.
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 of how to use this can be found in server_test.go.