Creating Expectations
To create an expectation you need to define:
- the request matcher and
- what response should be returned or
- where the request should be forwarded or
- what callback should be executed.
MockServer will play expectations in the exact order they are setup. For example, if an expectation A is setup to response (or forward) 3 times then expectation B is setup to response (or forward) 2 times for the same request MockServer will response (or forward) in the following order A, A, A, B, B.
Java
To setup an expectation that responds to a request:
new MockServerClient("127.0.0.1", 1080)
.when(
request()
.withMethod("POST")
.withPath("/login")
.withQueryStringParameters(
new Parameter("returnUrl", "/account")
)
.withCookies(
new Cookie("sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW")
)
.withBody(exact("{username: 'foo', password: 'bar'}")),
exactly(1)
)
.respond(
response()
.withStatusCode(401)
.withHeaders(
new Header("Content-Type", "application/json; charset=utf-8"),
new Header("Cache-Control", "public, max-age=86400")
)
.withBody("{ message: 'incorrect username and password combination' }")
.withDelay(new Delay(SECONDS, 1))
);
To setup an expectation that forwards to a request:
new MockServerClient("127.0.0.1", 1080)
.when(
request()
.withMethod("GET")
.withPath("/index.html"),
exactly(1)
)
.forward(
forward()
.withHost("www.mock-server.com")
.withPort(80)
.withScheme(HTTP)
);
To start a local instance of MockServer and setup an expectation that executes a callback:
MockServerClient mockServer = startClientAndServer(1080);
mockServer
.when(
request()
.withPath("/callback")
)
.callback(
callback()
.withCallbackClass("org.mockserver.server.PrecannedTestExpectationCallback")
);
and the callback class could be as follows:
public class PrecannedTestExpectationCallback implements ExpectationCallback {
public static HttpResponse httpResponse = response()
.withStatusCode(ACCEPTED_202.code())
.withHeaders(
header("x-callback", "test_callback_header"),
header("Content-Length", "a_callback_response".getBytes().length),
header("Connection", "keep-alive")
)
.withBody("a_callback_response");
@Override
public HttpResponse handle(HttpRequest httpRequest) {
if (httpRequest.getPath().getValue().endsWith("/callback")) {
return httpResponse;
} else {
return notFoundResponse();
}
}
}
Note: these examples require the use of these static imports as follows:
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
import static org.mockserver.model.HttpForward.forward;
import static org.mockserver.model.Header.header;
import static org.mockserver.model.HttpResponse.notFoundResponse;
import static org.mockserver.model.HttpResponse.response;
import static org.mockserver.matchers.Times.exactly;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.mockserver.model.HttpForward.Scheme.HTTP;
import static org.mockserver.model.HttpStatusCode.ACCEPTED_202;
The mockserver-example project contains multiple examples such as BookPageIntegrationTest that demonstrates a fully working examples.
JavaScript
To setup a simple expectation that returns a JSON body for all requests on a given path:
mockServerClient("localhost", 1080).mockSimpleResponse('/somePath', { name: 'value' }, 203);
To setup a more complex expectation:
mockServerClient("localhost", 1080).mockAnyResponse(
{
'httpRequest': {
'method': 'POST',
'path': '/somePath',
'queryStringParameters': [
{
'name': 'test',
'values': [ 'true' ]
}
],
'body': {
'type': 'STRING',
'value': 'someBody'
}
},
'httpResponse': {
'statusCode': 200,
'body': JSON.stringify({ name: 'value' }),
'delay': {
'timeUnit': 'MILLISECONDS',
'value': 250
}
},
'times': {
'remainingTimes': 1,
'unlimited': false
}
}
);
To setup an expectation that forwards all requests:
mockServerClient("localhost", 1080).mockAnyResponse(
{
'httpRequest': {
'method': 'GET',
'path': '/somePath'
},
"httpForward": {
"host": "www.mock-server.com",
"port": 80,
"scheme": "HTTP"
},
'times': {
'remainingTimes': 1,
'unlimited': false
}
}
);
It is also possible to make AJAX calls directly without the client as follows:
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:1080/expectation", false);
xmlHttpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xmlHttpRequest.send(JSON.stringify({
"httpRequest": {
"method": "POST",
"path": "/login",
"body": {
"type": "JSON",
"value": JSON.stringify({ username: "foo", password: "bar" })
}
},
"httpResponse": {
"statusCode": 401,
"headers": [
{
"name": "Content-Type",
"values": ["application/json; charset=utf-8"]
},
{
"name": "Cache-Control",
"values": ["public, max-age=86400"]
}
],
"body": JSON.stringify({ message: "incorrect username and password combination" })
}
}));
Ruby
To setup an expectation that responds to a request:
require "mockserver-client"
class SomeClass
include MockServer
include MockServer::Model::DSL
def createExpectation
client = MockServerClient.new('localhost', 1080)
expectation = expectation do |expectation|
expectation.request do |request|
request.method = 'POST'
request.path = '/login'
request.query_string_parameters << parameter('returnUrl', '/account')
request.cookies = [cookie('sessionId', '2By8LOhBmaW5nZXJwcmludCIlMDAzMW')]
request.body = exact({ username: 'foo', password: 'bar' }.to_json)
end
expectation.response do |response|
response.status_code = 401
response.headers << header('Content-Type', 'application/json; charset=utf-8')
response.headers << header('Cache-Control', 'public, max-age=86400')
response.body = body({ message: 'incorrect username and password combination' }.to_json)
response.delay = delay_by(:SECONDS, 1)
end
end
client.register(expectation)
end
end
To setup an expectation that forwards all requests:
client = MockServerClient.new('localhost', 1080)
expectation = expectation do |expectation|
expectation.request do |request|
request.method = 'GET'
request.path = '/somePath'
end
expectation.forward do |forward|
forward.host = 'www.mock-server.com'
forward.port = 80
forward.scheme = :HTTP
end
expectation.times = exactly(2)
end
client.register(expectation)
Request Matchers
To specify when a response should be mocked a request matcher must be provided in each expectation.
When an incoming request matches the request matcher in an expectation MockServer will return the response for that expectation.
Requests can be matched on:
- path - plain text or regular expression
- query string - plain text or regular expression
- headers - plain text or regular expression
- cookies - plain text or regular expression
- body - XPath, JSON, JSON Schema, regular expression, plain text (exact match), or body parameters
The body can be matched using plain text, a JSON object, a JSON schema, an XPath expression or a regular expression
JSON expressions
A JSON expression is a valid JSON object. When a JSON expression is matched against a request body the order of the fields will be ignored, if the exact order is important use a plain text or regular expression matcher.
The JSON expression supports two match types STRICT and ONLY_MATCHING_FIELDS. STRICT match type matches all fields and the order of arrays. In STRICT match type extra fields will cause the matcher to fail. ONLY_MATCHING_FIELDS match type only matches fields provided in the body for the request matcher. ONLY_MATCHING_FIELDS match type will match correctly against a request that contains additional fields or a request that contains any array fields those elements are in a different order.
JSON Schema
For detail of the support JSON Schema syntax see json-schema.org.
XPath
For detail of the support XPath syntax see XPath Expression Syntax.
Regular Expressions
All other matching can be done using plain text or a regular expression, see Pattern (Java Platform SE 6) for supported regular expression syntax.
Java Request Matcher API
To specify a request matcher in Java use the org.mockserver.model.HttpRequest class which specifies the details of each HTTP response with a fluent API:
public class HttpRequest {
/**
* The HTTP method to match on such as "GET" or "POST"
*
* @param method the HTTP method such as "GET" or "POST"
*/
public HttpRequest withMethod(String method);
/**
* The HTTP method all method except a specific value using the "not" operator,
* for example this allows operations such as not("GET")
*
* @param method the HTTP method to not match on not("GET") or not("POST")
*/
public HttpRequest withMethod(NottableString method);
/**
* The path to match on such as "/some_mocked_path" any servlet context path is ignored for matching and should not be specified here
* regex values are also supported such as ".*_path", see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
* for full details of the supported regex syntax
*
* @param path the path such as "/some_mocked_path" or a regex
*/
public HttpRequest withPath(String path);
/**
* The path to not match on for example not("/some_mocked_path") with match any path not equal to "/some_mocked_path",
* the servlet context path is ignored for matching and should not be specified here
* regex values are also supported such as not(".*_path"), see
* http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html for full details of the supported regex syntax
*
* @param path the path to not match on such as not("/some_mocked_path") or not(".*_path")
*/
public HttpRequest withPath(NottableString path);
/**
* The query string parameters to match on as a list of Parameter objects where the values or keys of each parameter
* can be either a string or a regex (for more details of the supported regex syntax
* see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param parameters the list of Parameter objects where the values or keys of each parameter can be either a string or a regex
*/
public HttpRequest withQueryStringParameters(List<Parameter> parameters);
/**
* The query string parameters to match on as a varags Parameter objects where the values or keys of each parameter
* can be either a string or a regex (for more details of the supported regex syntax
* see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param parameters the varags Parameter objects where the values or keys of each parameter can be either a string or a regex
*/
public HttpRequest withQueryStringParameters(Parameter... parameters);
/**
* The query string parameters to match on as a Map<String, List<String>> where the values or keys of each parameter
* can be either a string or a regex (for more details of the supported regex syntax
* see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param parameters the Map<String, List<String>> object where the values or keys of each parameter can be either a string or a regex
*/
public HttpRequest withQueryStringParameters(Map<String, List<String>> parameters);
/**
* Adds one query string parameter to match on as a Parameter object where the parameter values list can be a list of strings
* or regular expressions (for more details of the supported regex syntax
* see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param parameter the Parameter object which can have a values list of strings or regular expressions
*/
public HttpRequest withQueryStringParameter(Parameter parameter);
/**
* Adds one query string parameter to match on as a Parameter object where the parameter values list can be a list of strings
* or regular expressions (for more details of the supported regex syntax
* see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param name the parameter name
* @param values the parameter values which can be a varags of strings or regular expressions
*/
public HttpRequest withQueryStringParameter(String name, String... values);
/**
* The exact string body to match on such as "this is an exact string body"
*
* @param body the body on such as "this is an exact string body"
*/
public HttpRequest withBody(String body);
/**
* The body match rules on such as using one of the Body subclasses as follows:
*
* exact string match:
*
* - exact("this is an exact string body");
*
* or
*
* - new StringBody("this is an exact string body")
*
* regular expression match:
*
* - regex("username[a-z]{4}");
*
* or
*
* - new RegexBody("username[a-z]{4}");
*
* json match:
*
* - json("{username: 'foo', password: 'bar'}");
*
* or
*
* - json("{username: 'foo', password: 'bar'}", MatchType.STRICT);
*
* or
*
* - new JsonBody("{username: 'foo', password: 'bar'}");
*
* json schema match:
*
* - jsonSchema("{type: 'object', properties: { 'username': { 'type': 'string' }, 'password': { 'type': 'string' } }, 'required': ['username', 'password']}");
*
* or
*
* - jsonSchemaFromResource("org/mockserver/model/loginSchema.json");
*
* or
*
* - new JsonSchemaBody("{type: 'object', properties: { 'username': { 'type': 'string' }, 'password': { 'type': 'string' } }, 'required': ['username', 'password']}");
*
* xpath match:
*
* - xpath("/element[key = 'some_key' and value = 'some_value']");
*
* or
*
* - new XPathBody("/element[key = 'some_key' and value = 'some_value']");
*
* body parameter match:
*
* - params(
* param("name_one", "value_one_one", "value_one_two")
* param("name_two", "value_two")
* );
*
* or
*
* - new ParameterBody(
* new Parameter("name_one", "value_one_one", "value_one_two")
* new Parameter("name_two", "value_two")
* );
*
* binary match:
*
* - binary(IOUtils.readFully(getClass().getClassLoader().getResourceAsStream("example.pdf"), 1024));
*
* or
*
* - new BinaryBody(IOUtils.readFully(getClass().getClassLoader().getResourceAsStream("example.pdf"), 1024));
*
* for more details of the supported regular expression syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
* for more details of the supported json syntax see http://jsonassert.skyscreamer.org
* for more details of the supported json schema syntax see http://json-schema.org/
* for more detail of XPath syntax see http://saxon.sourceforge.net/saxon6.5.3/expressions.html
*
* @param body an instance of one of the Body subclasses including StringBody or ParameterBody
*/
public HttpRequest withBody(Body body);
/**
* The headers to match on as a list of Header objects where the values or keys of each header can be either a string or a regex
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param headers the list of Header objects where the values or keys of each header can be either a string or a regex
*/
public HttpRequest withHeaders(List<Header> headers);
/**
* The headers to match on as a varags of Header objects where the values or keys of each header can be either a string or a regex
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param headers the varags of Header objects where the values or keys of each header can be either a string or a regex
*/
public HttpRequest withHeaders(Header... headers);
/**
* Adds one header to match on as a Header object where the header values list can be a list of strings or regular expressions
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param header the Header object which can have a values list of strings or regular expressions
*/
public HttpRequest withHeader(Header header);
/**
* Adds one header to match on as a Header object where the header values list can be a list of strings or regular expressions
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param name the header name
* @param values the header values which can be a varags of strings or regular expressions
*/
public HttpRequest withHeader(String name, String... values);
/**
* The cookies to match on as a list of Cookie objects where the values or keys of each cookie can be either a string or a regex
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param cookies the list of Cookie objects where the values or keys of each cookie can be either a string or a regex
*/
public HttpRequest withCookies(List<Cookie> cookies);
/**
* The cookies to match on as a varags Cookie objects where the values or keys of each cookie can be either a string or a regex
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param cookies the varags Cookie objects where the values or keys of each cookie can be either a string or a regex
*/
public HttpRequest withCookies(Cookie... cookies);
/**
* Adds one cookie to match on as a Cookie object where the cookie values list can be a list of strings or regular expressions
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param cookie the Cookie object which can have a values list of strings or regular expressions
*/
public HttpRequest withCookie(Cookie cookie);
/**
* Adds one cookie to match on as a Cookie object where the cookie values list can be a list of strings or regular expressions
* (for more details of the supported regex syntax see http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)
*
* @param name the cookies name
* @param value the cookies value which can be a string or regular expression
*/
public HttpRequest withCookie(String name, String value);
}
For example:
HttpRequest httpRequest =
request()
.withMethod("POST")
.withPath("/login")
.withBody("{username: 'foo', password: 'bar'}")
.withQueryStringParameters(
new Parameter("returnUrl", "/account")
)
.withCookies(
new Cookie("sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW")
);
JavaScript Request Matcher API
To specify a request matcher in JavaScript use JSON to specify the details with the following format:
"httpRequest": {
"method": "",
"path": "",
"queryStringParameters": []
"body": {
"type": <"STRING" or "REGEX" or "JSON" or "JSON_SCHEMA" or "XPATH" or "PARAMETERS">,
"value": "" ( or "parameters" as shown in more detail below )
},
"cookies": [],
"headers": [],
}
Note: Only values which are matched on need to be specified, if a value is missing then it will not be matched on. For example, below both the parameters and headers fields are not specified.
Cookies, Headers, Parameters
Each cookie, header or parameter array entry has the following syntax:
{
"name": "someName",
"values": ["someValueOne", "someValueTwo", ...]
}
The same example, as in Java above, in JavaScript would be :
"httpRequest": {
"method": "POST",
"path": "/login",
"queryStringParameters": [
{
"name": "returnUrl",
"values": ["/account"]
}
],
"cookies": [
{
"name": "sessionId",
"values": ["2By8LOhBmaW5nZXJwcmludCIlMDAzMW"]
}
],
"body": {
"type": "STRING",
"value": "{username: 'foo', password: 'bar'}"
}
}
Bodies
The "type" value in "body" can be:
"STRING"
"REGEX"
"JSON"
"JSON_SCHEMA"
"XPATH"
"PARAMETERS"
When the "type" field has a value of "STRING", "REGEX", "JSON", "JSON_SCHEMA" or "XPATH" the other field of "body"" should be "value" and it should provide a string to perform the match against, as shown in the example above.
Parameter Bodies
When the "type" field has a value of "PARAMETERS" the other field of "body" should be "parameters" and it should provide a list of body parameters using the following syntax:
{
"name": "someName",
"values": ["someValueOne", "someValueTwo", ...]
}
For example:
"httpRequest": {
"method": "POST",
"path": "/login",
"queryStringParameters": [
{
"name": "returnUrl",
"values": ["/account"]
}
],
"cookies": [
{
"name": "sessionId",
"values": ["2By8LOhBmaW5nZXJwcmludCIlMDAzMW"]
}
],
"body": {
"type": "PARAMETERS",
"parameters": [
{
"name": "username",
"values": ["foo"]
},
{
"name": "password",
"values": ["bar"]
}
]
}
}
String Body Matcher
When the "type" field has a value of "STRING" a short hand can be used where the "body" is only specified as a string literal for example:
"httpRequest": {
"method": "POST",
"path": "/login",
"queryStringParameters": [
{
"name": "returnUrl",
"values": ["/account"]
}
],
"cookies": [
{
"name": "sessionId",
"values": ["2By8LOhBmaW5nZXJwcmludCIlMDAzMW"]
}
],
"body": "a string body showing the short-hand way to specify a simple string body"
}
JSON Object Body Matchers
When the "type" field has a value of "JSON" an additional field can be provided to specify the match type called "matchType".
The JSON expression supports two match types "STRICT" and "ONLY_MATCHING_FIELDS". "STRICT" match type matches all fields and the order of arrays. In "STRICT" match type extra fields will cause the matcher to fail. "ONLY_MATCHING_FIELDS" match type only matches fields provided in the body for the request matcher. "ONLY_MATCHING_FIELDS" match type will match correctly against a request that contains additional fields or a request that contains any array fields those elements are in a different order.
"httpRequest": {
"method": "POST",
"path": "/login",
"body": {
"type": "JSON",
"value": "{username: 'foo', password: 'bar'}",
"matchType": "STRICT"
}
}
JSON Schema Body Matcher
MockServer supports matching request bodies using JSON Schema, which is useful for matching or validating the format of a JSON object. The detailed syntax of JSON Schema is documented at http://json-schema.org.
To use JSON Schema to match a request body the "type" field should have a value of "JSON_SCHEMA" and the "value" field should contain the JSON Schema as a string value, as follows:
"httpRequest": {
"method": "POST",
"path": "/login",
"body": {
"type": "JSON_SCHEMA",
"value": "{
"type": "object",
"properties": {
"username": {
"type": "string",
"pattern": "^[a-z0-9_-]{3,15}$"
},
"password": {
"type": "string",
"minLength": 8
}
},
"required": [
"username",
"password"
]
}"
}
}
Response Actions (Mock Responses)
Response actions contain:
- status code i.e. 200, 302, 404, etc
- body - a UTF-8 encoded sequence of bytes containing any content
- headers - each with a name and one or more values
- cookies - each with a name and with one or more values, more complex cookies can be modelled by using the a Set-Cookie header
Responses can be further controlled using:
- a delay before the response is sent
- the number of times the response is sent (including unlimited)
- a time to live the response will be continued to be returned (including unlimited)
Java
When mocking a response in Java use the org.mockserver.model.HttpResponse class which specifies the details of each HTTP response with a fluent API, for example:
HttpResponse httpResponse =
response()
.withStatusCode(401)
.withHeaders(
new Header("Content-Type", "application/json; charset=utf-8"),
new Header("Cache-Control", "public, max-age=86400")
)
.withBody("{ message: 'incorrect username and password combination' }")
.withDelay(new Delay(TimeUnit.SECONDS, 1))
.withConnectionOptions(
new ConnectionOptions()
.withKeepAliveOverride(true)
.withCloseSocket(true)
);
The full specification of org.mockserver.model.HttpResponse is as follows:
public class HttpResponse {
/**
* The status code to return, such as 200, 404, the status code specified
* here will result in the default status message for this status code for
* example for 200 the status message "OK" is used
*
* @param statusCode an integer such as 200 or 404
*/
public HttpResponse withStatusCode(Integer responseCode);
/**
* The cookies to return as Set-Cookie headers as a list of Cookie objects
*
* @param cookies a list of Cookie objects
*/
public HttpResponse withCookies(List<Cookie> cookies);
/**
* The cookies to return as Set-Cookie headers as a varargs of Cookie objects
*
* @param cookies a varargs of Cookie objects
*/
public HttpResponse withCookies(Cookie... cookies);
/**
* Add cookie to return as Set-Cookie header
*
* @param cookie a Cookie object
*/
public HttpResponse withCookie(Cookie cookie);
/**
* Add cookie to return as Set-Cookie header
*
* @param name the cookies name
* @param value the cookies value which can be a string or regular expression
*/
public HttpResponse withCookie(String name, String value);
/**
* The headers to return as a list of Header objects
*
* @param headers a list of Header objects
*/
public HttpResponse withHeaders(List<Header> headers);
/**
* The headers to return as a varargs of Header objects
*
* @param headers a varargs of Header objects
*/
public HttpResponse withHeaders(Header... headers);
/**
* A header to return as a Header objects
*
* @param header a Header objects
*/
public HttpResponse withHeader(Header header)
/**
* A header to return as a Header objects
*
* @param name the header name
* @param values the header values which can be a varags of strings or regular expressions
*/
public HttpResponse withHeader(String name, String... values)
/**
* Set response body to return as a simple UTF-8 string response body
*
* @param body a "UTF-8" string
*/
public HttpResponse withBody(String body);
/**
* * Set response body to return as binary such as a pdf or image
*
* @param body a byte array
*/
public HttpResponse withBody(byte[] body);
/**
* Set the body to return for example:
*
* string body:
* - exact("<html><head/><body><div>a simple string body</div></body></html>"); or
* - new StringBody("<html><head/><body><div>a simple string body</div></body></html>")
*
* binary body:
* - binary(IOUtils.readFully(getClass().getClassLoader().getResourceAsStream("example.pdf"), 1024)); or
* - new BinaryBody(IOUtils.readFully(getClass().getClassLoader().getResourceAsStream("example.pdf"), 1024));
*
* @param body an instance of one of the Body subclasses including StringBody or BinaryBody
*/
public HttpResponse withBody(Body body);
/**
* The delay before responding with this request as a Delay object, for example new Delay(TimeUnit.SECONDS, 3)
*
* @param delay a Delay object, for example new Delay(TimeUnit.SECONDS, 3)
*/
public HttpResponse withDelay(Delay delay);
/**
* The connection options for override the default connection behaviour, this allows full control of headers such
* as "Connection" or "Content-Length" or controlling whether the socket is closed after the response has been sent
*
* @param connectionOptions the connection options for override the default connection behaviour
*/
public HttpResponse withConnectionOptions(ConnectionOptions connectionOptions);
}
To control whether the socket is closed after the response has been sent or headers such as "Connection" or "Content-Length" the org.mockserver.model.ConnectionOptions class can be used, as follows:
public class ConnectionOptions {
/**
* Prevent a "Content-Length" header from being added to the response
*
* @param suppressContentLengthHeader if true no "Content-Length" header will be added to the response
*/
public ConnectionOptions withSuppressContentLengthHeader(Boolean suppressContentLengthHeader);
/**
* Override the "Content-Length" header with the specified amount, if not set the "Content-Length"
* header will have a value determined by the length of the body
*
* @param contentLengthHeaderOverride the value to use for the "Content-Length" header
*/
public ConnectionOptions withContentLengthHeaderOverride(Integer contentLengthHeaderOverride);
/**
* Prevent a "Connection" header from being added to the response
*
* @param suppressConnectionHeader if true no "Connection" header will be added to the response
*/
public ConnectionOptions withSuppressConnectionHeader(Boolean suppressConnectionHeader);
/**
* Override the "Connection" header:
* if true the "Connection" header is specified with a value of "keep-alive"
* if false the "Connection" header is specified with a value of "close"
* if not set the "Connection" header will have a a value of "close" unless the request received is HTTP 1.1 and contains a "Connection" header with a value of "keep-alive"
*
* @param keepAliveOverride if true "keep-alive" is used if false "close" is used for the "Connection" header
*/
public ConnectionOptions withKeepAliveOverride(Boolean keepAliveOverride);
/**
* Override whether the socket is closed after a response is sent:
* if true the socket will always be closed,
* if false the socket will never be closed,
* if not set the socket will be closed unless the request received is HTTP 1.1 and contains a "Connection" header with a value of "keep-alive"
*
* @param closeSocket set whether the socket is closed after a response is sent
*/
public ConnectionOptions withCloseSocket(Boolean closeSocket);
}
For example:
HttpResponse httpResponse =
response()
.withStatusCode(401)
.withHeaders(
new Header("Content-Type", "application/json; charset=utf-8"),
new Header("Cache-Control", "public, max-age=86400")
)
.withBody("{ message: 'incorrect username and password combination' }")
.withDelay(new Delay(TimeUnit.SECONDS, 1))
.withConnectionOptions(
new ConnectionOptions()
.withKeepAliveOverride(true)
.withCloseSocket(true)
);
JavaScript
To mock a response in javascript use JSON to specify the details with the following format:
"httpResponse": {
"statusCode": 200,
"body": "",
"cookies": [],
"headers": [],
"delay": {
"timeUnit": "MICROSECONDS",
"value": 0
}
}
Each cookie or header array entry has the following syntax:
{
"name": "someName",
"values": ["someValueOne", "someValueTwo", ...]
}
The "timeUnit" value in "delay" can be:
"NANOSECONDS"
"MICROSECONDS"
"MILLISECONDS"
"SECONDS"
"MINUTES"
"HOURS"
"DAYS"
The same example as above would be:
"httpResponse": {
"statusCode": 401,
"headers": [
{
"name": "Content-Type",
"values": ["application/json; charset=utf-8"]
},
{
"name": "Cache-Control",
"values": ["public, max-age=86400"]
}
],
"body": JSON.stringify({ message: "incorrect username and password combination" }),
"delay": {
"timeUnit": "SECONDS",
"value": 1
}
}
Forward Actions
Forward actions contain:
- host - the host to forward to i.e. www.mock-server.com
- port - the port to forward to, this defaults to 80 if not specified
- scheme - the scheme to use, either HTTP or HTTPS, this defaults to HTTP if not specified
Forward actions can be further controlled using:
- the number of times the request is forwarded (including unlimited)
- a time to live the response will be continued to be returned (including unlimited)
Java
When mocking a forward in Java use the org.mockserver.model.HttpForward class which specifies the details of each HTTP(S) forward with a fluent API, for example:
HttpForward httpForward =
forward()
.withHost("www.mock-server.com")
.withPort(80)
.withScheme(HttpForward.Scheme.HTTP);
The full specification of org.mockserver.model.HttpForward is as follows:
public class HttpForward {
/**
* The host or ip address to forward the request to i.e. "www.mock-server.com"
*
* @param host a hostname or ip address as a string
*/
public HttpForward withHost(String host);
/**
* The port to forward the request to i.e. 80. If not specified the port defaults to 80.
*
* @param port a port as an integer
*/
public HttpForward withPort(Integer port);
/**
* The scheme to use when forwarded the request, either HTTP or HTTPS. If not specified the scheme defaults to HTTP.
*
* @param scheme the scheme as a HttpForward.Scheme value
*/
public HttpForward withScheme(Scheme scheme);
}
JavaScript
To mock a response in javascript use JSON to specify the details with the following format:
"httpForward": {
"host": "",
"port": 80,
"scheme": "HTTP"
}
The "scheme" value in can be:
"HTTP"
"HTTPS"
The same example as above would be:
"httpForward": {
"host": "www.mock-server.com",
"port": 80,
"scheme": "HTTP"
}
Callback Actions
A callback specifies a class that will be called for each matching request and can be used to dynamically generate the response.
Callback actions contain:
- callbackClass
The callback class must:
- have a default constructor
- implement org.mockserver.mock.action.ExpectationCallback
- be available on the classpath (see below)
Callback actions can be further controlled using:
- the number of times the callback is called (including unlimited)
- a time to live the callback will be continued to be called (including unlimited)
If MockServer is started using the JUnitRule org.mockserver.junit.MockServerRule or using org.mockserver.integration.ClientAndServer or directly using the org.mockserver.mockserver.MockServerBuilder then any class present in the main or test classpaths will be visible to MockServer.
If MockServer is started using the plugin only the non-forked goals (such as runAndWait and start) will be able to load classes from the main and test classpaths. It is possible to use classes from a separate maven dependency, however, this dependency must be specified in the plugin configuration dependencies section. Any dependency added to the plugin configuration dependencies section will then be visible to MockServer run using both forked and non-forked goals.
The following configuration shows how to use classes from a separate maven dependency in callback actions.
<plugin>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-maven-plugin</artifactId>
<version>4.0.0</version>
<configuration>
<serverPort>1080</serverPort>
<logLevel>DEBUG</logLevel>
<pipeLogToConsole>true</pipeLogToConsole>
</configuration>
<executions>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>runForked</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>stopForked</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.my-domain</groupId>
<artifactId>my-callback-dependency</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</plugin>
If MockServer is started using the command line then the callback classes must be added to the JVM using the classpath command line switch (cp or classpath). The classpath switch is ignored by the JVM if the jar switch is used. So to run the MockServer from the command line directly (with mockserver-netty-4.0.0-jar-with-dependencies.jar) you must specify the org.mockserver.cli.Main main class specifically and not use the jar switch as follows.
java -Dfile.encoding=UTF-8 -cp mockserver-netty-4.0.0-jar-with-dependencies.jar:my-callback-dependency.jar org.mockserver.cli.Main -serverPort 1080
Java
When mocking a callback in Java use the org.mockserver.model.HttpClassCallback class which specifies the details class to callback as follows, for example:
HttpCallback httpClassCallback = callback("org.some.package.MyCallback");
The full specification of org.mockserver.model.HttpClassCallback is as follows:
public class HttpCallback {
/**
* The class to callback as a fully qualified class name
*
* This calls must:
* - implement org.mockserver.mock.action.ExpectationCallback
* - have a zero argument constructor
* - be available in the classpath of the MockServer
*
* @param callbackClass class to callback as a fully qualified class name, i.e. "com.foo.MyExpectationCallback"
*/
public HttpCallback withCallbackClass(String callbackClass);
}
The class specified must implement the org.mockserver.mock.action.ExpectationCallback interface as follows:
public interface ExpectationCallback {
/**
* Called for every request when expectation condition has been satisfied.
* The request that satisfied the expectation condition is passed as the
* parameter and the return value is the response that will be returned to the client.
*
* @param httpRequest the request that satisfied the expectation condition
* @return the response that will be returned to the client
*/
public HttpResponse handle(HttpRequest httpRequest);
}
Times
The org.mockserver.matchers.Times class is used to specify how many times you want MockServer to match a request:
To create an instance of Times use one of the static factory methods:
Times.unlimited();
Times.once();
Times.exactly(int count);
JavaScript
To setup a callback in javascript use JSON to specify the details with the following format:
"httpClassCallback": {
"callbackClass": "org.mypackage.MyCallbackClass"
}