The MockServer Proxy allows the verification of requests by specifying:

  • an amount of a single type of request
  • a sequence of requests that is verified in order

Verifying Repeating Requests

To verify that a request has been sent use the verify method of the ProxyClient as follows:

new ProxyClient("localhost", 1090).verify(
        request()
                .withMethod("POST")
                .withPath("/login")
                .withBody(exact("{username: 'foo', password: 'bar'}"))
                .withCookies(
                        new Cookie("sessionId", ".*")
                ),
        VerificationTimes.exactly(1)
);

The org.mockserver.verify.VerificationTimes class is used to specify how many times you want MockServer to match a request:

To create an instance of VerificationTimes use one of the static factory methods:

VerificationTimes.once();
VerificationTimes.exactly(int count);
VerificationTimes.atLeast(int count);

Verifying Request Sequences

To verify that the system under test has sent a sequence of requests to MockServer use the verify method of the MockServerClient as follows:

new ProxyClient("localhost", 1090).verify(
        request()
                .withMethod("POST")
                .withPath("/login")
                .withBody(exact("{username: 'foo', password: 'bar'}"))
                .withCookies(
                        new Cookie("sessionId", ".*")
                ),
        request()
                .withMethod("POST")
                .withPath("/deposit")
                .withBody(exact("{acccount: '123456789', card: '1234 5678 9012 3456', amount: '10.00'}"))
                .withCookies(
                        new Cookie("sessionId", ".*")
                ),
        request()
                .withMethod("POST")
                .withPath("/logout")
                .withCookies(
                        new Cookie("sessionId", ".*")
                )
);

The each request in the sequence will be verified to have been received at least once, in the exact order specified.

The mockserver-example project contains an example test called BookPageIntegrationTest that demonstrates a fully working example.

Request Matchers

For each verification a request matcher is used to specify how and what should be verified.

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"
            ]
        }"
    }
}