MockServer

Easy mocking of any system you integrate with via HTTP or HTTPS

Fork us on GitHub  
Drone.io Build Status Codeship Build Status

What is MockServer

MockServer is for mocking of any system you integrate with via HTTP or HTTPS (i.e. services, web sites, etc).

MockServer supports:

  • mocking of any HTTP / HTTPS response when any request is matched (see more below)
  • recording requests and responses to analyse how a system behaves (see more below)
  • verifying which requests and responses have been sent as part of a test (see more below)

MockServer Clients:

There are currently clients written in Java and JavaScript (see more below) although any language that can send JSON via HTTP can easily use the MockServer API.

 

Mocking

To mock an HTTP / HTTPS interaction an expectation is setup specifying how a request should be matched and what response the MockServer should reply with when the request has been matched.

For example to create an expectation using Java:

new MockServerClient("localhost", 9999)
        .when(
                request()
                        .withMethod("POST")
                        .withPath("/login")
                        .withQueryStringParameters(
                                new Parameter("returnUrl", "/account")
                        )
                        .withCookies(
                                new Cookie("sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW")
                        )
                        .withBody("{username: 'foo', password: 'bar'}"),
                Times.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(TimeUnit.SECONDS, 1))
        );

Or to create an expectation using JavaScript:

mockServerClient("http://localhost:9999").mockAnyResponse({
    "httpRequest": {
        "method": "POST",
        "path": "/login",
        "queryStringParameters": [
            {
                "name": "returnUrl",
                "values": ["/account"]
            }
        ],
        "cookies": [
            {
                "name": "sessionId",
                "values": ["2By8LOhBmaW5nZXJwcmludCIlMDAzMW"]
            }
        ],
        "body": {
            "type": "EXACT",
            "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" }),
        "delay": {
            "timeUnit": "SECONDS",
            "value": 1
        }
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
});

Requests can be matched on:

  • url - regex or plain text
  • path - regex or plain text
  • query string - regex or plain text
  • headers - regex or plain text
  • cookies - regex or plain text
  • body - XPath, json, regex, plain text (exact match), or body parameters

The body can be matched using plain text, a json expression, an XPath expression or a regular expression, see XPath Expression Syntax for supported XPath syntax.

All other matching can be done using plain text or a regular expression, see Pattern (Java Platform SE 7) for supported regular expression syntax.

Responses can contain:

  • status code
  • body
  • headers
  • cookies

Responses can be further controlled using:

  • a delay before the response is sent
  • the number of times the response is sent (including unlimited)

For more details see the section below on creating expectations.

 

Proxying

MockServer also provides an HTTP / HTTPS proxy that can be used to record requests / responses.

Once requests / responses have been recorded:

  • They can be queried pragmatically to confirm what requests have been sent and what responses have been received.
    • This supports test assertions that confirm what requests the system-under-test has been sending during a test.
  • They can be output in JSON format to log what request the system under has sent and what responses it received.
    • This is useful for analysing an existing system prior to writing automated tests.
    • This is also useful to simplify the creation of test setup code as the JSON output is in the MockServer expectation format.
  • They can be output in human readable Java code format that can be pasted directly into a test setup method.
    • This is useful to simplify the creation of expectations in test setup methods as the code can be easily pasted directly into a test setup method and then modified as appropriate for the needs of the test scenario.

For example to use the proxy to verify a request has been sent:

new ProxyClient("localhost", 9999)
        .verify(
                request()
                        .withMethod("POST")
                        .withPath("/login")
                        .withBody("{username: 'foo', password: 'bar'}"),
                Times.exactly(1)
        );

For example to use the proxy to print recorded requests and response to the log as JSON:

new ProxyClient("localhost", 9999)
        .dumpToLogAsJSON(
                request()
                        .withPath("/login")
        );

This would result in entries in the mockserver_request.log file of the following format:

2014-01-11 13:08:54,225 {
    "httpRequest": {
        "method": "POST",
        "url": "http://localhost:2021/login",
        "path": "/login",
        "body": {
            "type": "EXACT",
            "value": "{username: 'foo', password: 'bar'}",
        },
        "cookies": [
            {
                "name": "sid",
                "values": [ "05F1A3D2F2143C49727" ]
            }
        ],
        "headers": [
            {
                "name": "Accept-Language",
                "values": [ "en-US,en;q=0.8,fa;q=0.6" ]
            },
            {
                "name": "Cookie",
                "values": [ "sid=05F1A3D2F2143C49727" ]
            },
            {
                "name": "Host",
                "values": [ "localhost:2021" ]
            },
            {
                "name": "Content-Length",
                "values": [ "34" ]
            },
            {
                "name": "Accept-Encoding",
                "values": [ "gzip,deflate,sdch" ]
            },
            {
                "name": "User-Agent",
                "values": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" ]
            },
            {
                "name": "Accept",
                "values": [ "*/*" ]
            },
            {
                "name": "Content-Type",
                "values": [ "text/plain" ]
            }
        ]
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{ message: 'success' }",
        "headers": [
            {
                "name": "Content-Type",
                "values": [ "application/json; charset=utf-8" ]
            },
            {
                "name": "Cache-Control",
                "values": [ "no-cache, no-store" ]
            }
        ]
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}
 

Versions

MockServer is flexible and support numerous usage patterns.

The mock server can be run:

  • via the mockserver-maven-plugin, for example, as part of a build cycle
  • programmatically via an API, for example, in an @Before / @After method
  • from the command line as a stand-alone process, for example, as part of a deployment process to a test environment

MockServer is available as:

  • a stand alone Embedded Jetty web server that is fully self contained
  • a deployable WAR that runs on any JEE web server
  • a Vert.X module that runs on a Vert.X
 

Clients

MockServer has the following clients:

Note: It is not necessary to use the provided clients because the protocol is very simple JSON/HTTP.

  • Java
    • org.mockserver.client.server.MockServerClient - supports:
      • creating expectations
      • clearing expectations (selectively)
      • resetting (clearing all expectations)
      • dumping all expectations to the log (for debugging)
      • verifying which requests have been received
    • org.mockserver.client.proxy.ProxyClient - supports:
      • verifying which requests have been recorded
      • retrieving all recorded requests / responses as JSON or Expectation objects
      • outputting to the log all recorded requests / responses as Expectations in JSON format
      • outputting to the log all recorded requests / responses as Expectations in Java code format that can be pasted into test setup methods
      • clearing recorded requests / responses (selectively)
      • resetting (clearing all recorded requests / responses)
  • JavaScript
    • mockServerClient.js - supports:
      • creating expectations
      • clearing expectations (selectively)
      • resetting (clearing all expectations)
      • dumping all expectations to the log (for debugging)
      • verifying which requests have been received
    • proxyClient.js - supports:
      • verifying which requests have been recorded
      • retrieving all recorded requests / responses as JSON or Expectation objects
      • outputting to the log all recorded requests / responses as Expectations in JSON format
      • clearing recorded requests / responses (selectively)
      • resetting (clearing all recorded requests / responses)
 

Java MockServer Client

To simplest way to interact with MockServer from Java is to use org.mockserver.client.server.MockServerClient which provides the following API:

public class MockServerClient {

    /**
     * Start the client communicating to a MockServer at the specified host and port
     * for example:
     *
     *   MockServerClient mockServerClient = new MockServerClient("localhost", 8080);
     *
     * @param host the host for the MockServer to communicate with
     * @param port the port for the MockServer to communicate with
     */
    public MockServerClient(String host, int port);

    /**
     * Start the client communicating to a MockServer at the specified host and port
     * and contextPath for example:
     *
     *   MockServerClient mockServerClient = new MockServerClient("localhost", 8080);
     *
     * @param host the host for the MockServer to communicate with
     * @param port the port for the MockServer to communicate with
     * @param contextPath the context path that the MockServer war is deployed to
     */
    public MockServerClient(String host, int port, String contextPath);

    /**
     * Specify an unlimited expectation that will respond regardless of the number of matching http
     * for example:
     *
     *   mockServerClient
     *           .when(
     *                   request()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body")
     *           )
     *           .respond(
     *                   response()
     *                           .withBody("some_response_body")
     *                           .withHeaders(
     *                                   new Header("responseName", "responseValue")
     *                           )
     *           );
     *
     * @param httpRequest the http request that must be matched for this expectation to respond
     * @return an Expectation object that can be used to specify the response
     */
    public ForwardChainExpectation when(HttpRequest httpRequest);

    /**
     * Specify an limited expectation that will respond a specified number of times when the http is matched
     * for example:
     *
     *   mockServerClient
     *           .when(
     *                   new HttpRequest()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body"),
     *                   Times.exactly(5)
     *           )
     *           .respond(
     *                   new HttpResponse()
     *                           .withBody("some_response_body")
     *                           .withHeaders(
     *                                   new Header("responseName", "responseValue")
     *                           )
     *           );
     *
     * @param httpRequest the http request that must be matched for this expectation to respond
     * @param times       the number of times to respond when this http is matched
     * @return an Expectation object that can be used to specify the response
     */
    public ForwardChainExpectation when(HttpRequest httpRequest, Times times);

    /**
     * Pretty-print the json for all expectations to the log.  They are printed into a dedicated log called mockserver_request.log
     */
    public MockServerClient dumpToLog();

    /**
     * Pretty-print the json for all expectations that match the request to the log.  They are printed into a dedicated log called mockserver_request.log
     *
     * @param httpRequest the http request that is matched against when deciding what to log if null all requests are logged
     */
    public MockServerClient dumpToLog(HttpRequest httpRequest);

    /**
     * Reset MockServer by clearing all expectations
     */
    public MockServerClient reset();

    /**
     * Stop MockServer gracefully (only support for Netty and Vert.X versions, not supported for WAR version)
     */
    public MockServerClient stop();

    /**
     * Clear all expectations that match the http
     *
     * @param httpRequest the http request that is matched against when deciding whether to clear each expectation if null all expectations are cleared
     */
    public MockServerClient clear(HttpRequest httpRequest);

    /**
     * Verify a request has been sent for example:
     *
     *   mockServerClient
     *           .verify(
     *                   request()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body")
     *           );
     *
     * @param httpRequests the http requests that must be matched for this verification to pass
     * @throws AssertionError if the request has not been found
     */
    public MockServerClient verify(HttpRequest... httpRequests); throws AssertionError

    /**
     * Verify a request has been sent for example:
     *
     *   mockServerClient
     *           .verify(
     *                   request()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body"),
     *                   Times.exactly(3)
     *           );
     *
     * Times supports multiple static factory methods:
     *
     *   once()      - verify the request was only received once
     *   exactly(n)  - verify the request was only received exactly n times
     *   atLeast(n)  - verify the request was only received at least n times
     *
     * @param httpRequest the http request that must be matched for this verification to pass
     * @param times       the number of times this request must be matched
     * @throws AssertionError if the request has not been found
     */
    public MockServerClient verify(HttpRequest httpRequest, org.mockserver.client.proxy.Times times); throws AssertionError

    /**
     * Retrieve the recorded requests that match the httpRequest parameter as expectations, use null for the parameter to retrieve all requests
     *
     * @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null to retrieve for all requests
     * @return an array of all expectations that have been recorded by the proxy
     */
    public Expectation[] retrieveAsExpectations(HttpRequest httpRequest);

    /**
     * Retrieve the recorded requests that match the httpRequest parameter as a JSON array, use null for the parameter to retrieve all requests
     *
     * @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null to retrieve for all requests
     * @return a JSON array of all expectations that have been recorded by the proxy
     */
    public String retrieveAsJSON(HttpRequest httpRequest);
}
 

Java Proxy Client

To simplest way to interact with proxy from Java is to use org.mockserver.client.proxy.ProxyClient which provides the following API:

public class ProxyClient {

    /**
     * Start the client communicating to the proxy at the specified host and port
     * for example:
     *   ProxyClient mockServerClient = new ProxyClient("localhost", 1080);
     *
     * @param host the host for the proxy to communicate with
     * @param port the port for the proxy to communicate with
     */
    public ProxyClient(String host, int port);

    /**
     * Pretty-print the json for all requests / responses as Expectations to the log.
     * They are printed into a dedicated log called mockserver_request.log
     */
    public ProxyClient dumpToLogAsJSON();

    /**
     * Pretty-print the json for matching requests and their responses as Expectations to the log.
     * They are printed into a dedicated log called mockserver_request.log
     *
     * @param httpRequest the http request that is matched against when deciding what to log if null all requests are logged
     */
    public ProxyClient dumpToLogAsJSON(HttpRequest httpRequest);

    /**
     * Output Java code for creating all requests / responses as Expectations to the log.
     * They are printed into a dedicated log called mockserver_request.log
     */
    public ProxyClient dumpToLogAsJava();

    /**
     * Output Java code for creating matching requests and their responses as Expectations to the log.
     * They are printed into a dedicated log called mockserver_request.log
     *
     * @param httpRequest the http request that is matched against when deciding what to log if null all requests are logged
     */
    public ProxyClient dumpToLogAsJava(HttpRequest httpRequest);

    /**
     * Reset the proxy by clearing recorded requests
     */
    public ProxyClient reset();

    /**
     * Stop the proxy gracefully (only support for Netty and Vert.X versions, not supported for WAR version)
     */
    public ProxyClient stop();

    /**
     * Clear all recorded requests that match the httpRequest parameter
     *
     * @param httpRequest the http request that is matched against when deciding whether to clear recorded requests
     */
    public ProxyClient clear(HttpRequest httpRequest);

    /**
     * Verify a request has been sent for example:
     *
     *   mockServerClient
     *           .verify(
     *                   request()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body")
     *           );
     *
     * @param httpRequest the http request that must be matched for this verification to pass
     * @throws AssertionError if the request has not been found
     */
    public ProxyClient verify(HttpRequest httpRequest); throws AssertionError

    /**
     * Verify a request has been sent for example:
     *
     *   mockServerClient
     *           .verify(
     *                   request()
     *                           .withPath("/some_path")
     *                           .withBody("some_request_body"),
     *                   Times.exactly(3)
     *           );
     *
     * Times supports multiple static factory methods:
     *
     *   once()      - verify the request was only received once
     *   exactly(n)  - verify the request was only received exactly n times
     *   atLeast(n)  - verify the request was only received at least n times
     *
     * @param httpRequest the http request that must be matched for this verification to pass
     * @param times       the number of times this request must be matched
     * @throws AssertionError if the request has not been found
     */
    public ProxyClient verify(HttpRequest httpRequest, Times times); throws AssertionError

    /**
     * Retrieve the recorded requests that match the httpRequest parameter as expectations, use null for the parameter to retrieve all requests
     *
     * @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
     * @return an array of all expectations that have been recorded by the proxy
     */
    public Expectation[] retrieveAsExpectations(HttpRequest httpRequest);

    /**
     * Retrieve the recorded requests that match the httpRequest parameter as a JSON array, use null for the parameter to retrieve all requests
     *
     * @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
     * @return a JSON array of all expectations that have been recorded by the proxy
     */
    public String retrieveAsJSON(HttpRequest httpRequest);
}
 

JavaScript MockServer Client

To simplest way to interact with MockServer from JavaScript is to use mockServerClient.js.

To include this file is an HTML page use one of the following script tag to load the file from MaxCDN:

<script type="text/javascript" src="https://cdn.rawgit.com/jamesdbloom/mockserver/01973e75099bbc2ad2e37f809e9b33c8d31cb6dd/mockserver-javascript-client/src/main/javascript/mockServerClient.js"></script>

mockServerClient.js provides the following API:

var mockServerClient = function (mockServerUrl) {
    "use strict";

    /**
     * The default headers added to to the mocked response when using mockSimpleResponse(...)
     */
    var defaultResponseHeaders = [
            {'name': 'Content-Type', 'values': ['application/json; charset=utf-8']},
            {'name': 'Cache-Control', 'values': ['no-cache, no-store']}
    ],

    /**
     * Setup an expectation in the MockServer by specifying an expectation object
     * for example:
     *
     *   mockServerClient('localhost', 1080).mockAnyResponse(
     *       {
     *           'httpRequest': {
     *               'path': '/somePath',
     *               'body': {
     *                   'type': 'EXACT',
     *                   'value': 'someBody'
     *               }
     *           },
     *           'httpResponse': {
     *               'statusCode': 200,
     *               'body': Base64.encode(JSON.stringify({ name: 'first_body' })),
     *               'delay': {
     *                   'timeUnit': 'MILLISECONDS',
     *                   'value': 250
     *               }
     *           },
     *           'times': {
     *               'remainingTimes': 1,
     *               'unlimited': false
     *           }
     *       }
     *   );
     *
     * @param expectation the expectation to setup on the MockServer
     */
    mockAnyResponse = function (expectation),

    /**
     * Setup an expectation in the MockServer without having to specify the full expectation object
     * for example:
     *
     *   mockServerClient('localhost', 1080).mockSimpleResponse('/somePath', { 'name': 'value' }, 203);
     *
     * @param path         the path to match requests against
     * @param responseBody the response body to return if a request matches
     * @param statusCode   the response code to return if a request matches
     */
    mockSimpleResponse = function (path, responseBody, statusCode),

    /**
     * Override the default headers that are used to specify the response headers in mockSimpleResponse(...)
     * (note: if you use mockAnyResponse(...) the default headers are not used)
     * for example:
     *
     *   mockServerClient('localhost', 1080).setDefaultHeaders([
     *       {'name': 'Content-Type', 'values': ['application/json; charset=utf-8']},
     *       {'name': 'Cache-Control', 'values': ['no-cache, no-store']}
     *   ])
     *
     * @param headers the path to match requests against
     */
    setDefaultHeaders = function (headers),

    /**
     * Verify a request has been sent for example:
     *
     *   client.verify({
     *       'httpRequest': {
     *           'method': 'POST',
     *           'path': '/somePath'
     *       }
     *   }, 2, true);
     *
     * @param request the http request that must be matched for this verification to pass
     * @param count   the number of times this request must be matched
     * @param exact   true if the count is matched as "equal to" or false if the count is matched as "greater than or equal to"
     * @throws an error is the verify fails detailing which requests have been sent
     */
    verify = function (request, count, exact),

    /**
     * Reset MockServer by clearing all expectations
     */
    reset = function (path),

    /**
     * Clear all expectations that match the specified path
     *
     * @param path the path to decide which expectations to cleared
     */
    clear = function (path),

    /**
     * Pretty-print the json for all expectations for the specified path.
     * This is particularly helpful when debugging expectations. The expectation
     * are printed into a dedicated log called mockserver_request.log
     *
     * @param path the path to decide which expectations to dump to the log
     */
    dumpToLogs = function (path);

    return {
        mockAnyResponse: mockAnyResponse,
        mockSimpleResponse: mockSimpleResponse,
        setDefaultHeaders: setDefaultHeaders,
        verify: verify,
        reset: reset,
        clear: clear,
        dumpToLogs: dumpToLogs
    };
};
 

JavaScript Proxy Client

To simplest way to interact with the proxy from JavaScript is to use proxyClient.js.

To include this file is an HTML page use one of the following script tag to load the file from MaxCDN:

<script type="text/javascript" src="https://cdn.rawgit.com/jamesdbloom/mockserver/01973e75099bbc2ad2e37f809e9b33c8d31cb6dd/mockserver-javascript-client/src/main/javascript/proxyClient.js"></script>

proxyClient.js provides the following API:

var proxyClient = function (host, port) {
    "use strict";

    /**
     * Retrieve the recorded requests that match the httpRequest parameter as a JSON array, use null for the parameter to retrieve all requests
     *
     * @param request the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
     * @param a JSON array of all expectations that have been recorded by the proxy
     */
    var retrieve = function (request),

    /**
     * Verify a request has been sent for example:
     *
     *   client.verify({
     *       'httpRequest': {
     *           'method': 'POST',
     *           'path': '/somePath'
     *       }
     *   }, 2, true);
     *
     * @param request the http request that must be matched for this verification to pass
     * @param count   the number of times this request must be matched
     * @param exact   true if the count is matched as "equal to" or false if the count is matched as "greater than or equal to"
     * @throws an error is the verify fails detailing which requests have been sent
     */
    verify = function (request, count, exact),

    /**
     * Reset the proxy by clearing all recorded requests
     */
    reset = function (),

    /**
     * Clear all recorded requests that match the specified path
     *
     * @param path the path to decide which expectations to cleared
     */
    clear = function (path),

    /**
     * Pretty-print the json for all requests / responses that match the specified path
     * as Expectations to the log. They are printed into a dedicated log called mockserver_request.log
     *
     * @param path the path to decide which expectations to dump to the log
     */
    dumpToLogs = function (path);

    return {
        retrieve: retrieve,
        verify: verify,
        reset: reset,
        clear: clear,
        dumpToLogs: dumpToLogs
    };
};
 

Why use MockServer

MockServer allows you to mock any server or service that you connect to over HTTP or HTTPS, such as a REST or RPC service.

This is useful in the following scenarios:

  • testing
    • easily recreate all types of responses for HTTP dependencies such as REST or RPC services to test applications easily and affectively
    • isolate the system under test to ensure tests run reliably and only fail when there is a genuine bug. It is important only the system under test is tested and not its dependencies to avoid tests failing due to irrelevant external changes such as network failure or a server being rebooted / redeployed.
    • easily setup mock responses independently for each test to ensure test data is encapsulated with each test. Avoid sharing data between tests that is difficult to manage and maintain and risks tests infecting each other.
  • de-coupling development
    • start working against a service API before the service is available. If an API or service is not yet fully developed MockServer can mock the API allowing any team who is using the service to start work without being delayed.
    • isolate development teams particularly critical during the initial development phases when the APIs / services may be extremely unstable and volatile. Using the MockServer allows development work to continue even when an external service fails.

A system with service dependencies as follows:

System In Production

Could be tested with MockServer, mocking the service dependencies, as follows:

Mocking service dependencies with MockServer

 

Getting Started

To use the MockServer:

  1. Start MockServer
  2. Create Expectations
  3. Verify Behaviour
  4. Run Tests
 

Starting MockServer

Before any mock expectation can be sent to the MockServer it must be started.

The mock server can be run:

MockServer is available as:

  • a stand alone Netty web server that is fully self contained
  • a deployable WAR that runs on any JEE web server
  • a fully encapsulated Docker container
  • a Vert.X module that runs on a Vert.X

It is also possible to build and run the MockServer directly from source code as described below

 

Maven Plugin

To run MockServer as part of your build add the following plugin to your pom.xml:

<plugin>
    <groupId>org.mock-server</groupId>
    <artifactId>mockserver-maven-plugin</artifactId>
    <version>3.4</version>
    <configuration>
        <serverPort>1080</serverPort>
        <serverSecurePort>1082</serverSecurePort>
        <proxyPort>1090</proxyPort>
        <proxySecurePort>1092</proxySecurePort>
        <logLevel>DEBUG</logLevel>
        <initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
    </configuration>
    <executions>
        <execution>
            <id>process-test-classes</id>
            <phase>process-test-classes</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>verify</id>
            <phase>verify</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>

This will start the MockServer during the process-test-classes phase and will stop the MockServer during the verify phase. For more details about Maven build phases see: Introduction to the Build Lifecycle.

This ensures that any integration tests you run during the test or integration-test phases can use the MockServer on the port specified.

It is also possible to run the MockServer as a forked JVM using the runForked and stopForked goals as follows:

 <plugin>
     <groupId>org.mock-server</groupId>
     <artifactId>mockserver-maven-plugin</artifactId>
     <version>3.4</version>
     <configuration>
        <serverPort>1080</serverPort>
        <serverSecurePort>1082</serverSecurePort>
        <proxyPort>1090</proxyPort>
        <proxySecurePort>1092</proxySecurePort>
        <logLevel>DEBUG</logLevel>
        <initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
     </configuration>
     <executions>
         <execution>
             <id>process-test-classes</id>
             <phase>process-test-classes</phase>
             <goals>
                 <goal>runForked</goal>
             </goals>
         </execution>
         <execution>
             <id>verify</id>
             <phase>verify</phase>
             <goals>
                 <goal>stopForked</goal>
             </goals>
         </execution>
     </executions>
 </plugin>

Note: If you use the runForked goal as above and the test phase fails (because a test has failed) the MockServer will not be stopped as Maven does not run any more phases after a phase has failed. In the case above the verify phase is not run if a test fails so the forked MockServer will not be stopped. If you want to ensure the MockServer is stopped even when there are test failures make sure you use start and stop goals as these run the MockServer on a separate thread that is stopped however maven exits (even if a test fails).

These goals can be used from the command line as well to start and stop MockServer, as follows:

To run the MockServer synchronously and block:

mvn mockserver:run

To run the MockServer asynchronously as a forked JVM:

mvn mockserver:runForked

To stop a forked instance of the MockServer running on the same machine:

mvn mockserver:stopForked

The stopForked goal does assumes that the MockServer is running on the same physical machine as it uses 127.0.0.1 to communicate with the MockServer stop socket.

The Maven plugin has the following goals:

  • start - start MockServer, do not block, but stop when build ends
  • stop - stop a MockServer started earlier as part of the current build
  • run - run MockServer and block waiting for requests (timeout config if provided limits how long to block for)
  • runForked - run MockServer as separate forked JVM, do not block, stay alive when build ends
  • stopForked - stop a forked MockServer, previously started by a runForked goal

The Maven plugin can be configured as follows:

  • serverPort - The port the MockServer listens to incoming HTTP requests (required: false - but at least one of the four ports must be specified)
  • serverSecurePort - The port the MockServer listens to incoming HTTPS requests (required: false - but at least one of the four ports must be specified)
  • proxyPort - The port the proxy listens to incoming HTTP (and HTTP -> HTTPS CONNECT) requests (required: false - but at least one of the four ports must be specified)
  • proxySecurePort - The port the proxy listens to incoming HTTPS requests (required: false - but at least one of the four ports must be specified)
  • timeout - How long to block waiting for MockServer, used by run goal, 0 means wait indefinitely (required: false, default: 0)
  • logLevel - The logging level (required: false, default: WARN)
  • skip - Prevent the plugin from running (required: false, default: false)
  • initializationClass - To enable the creation of default expectations that are generic across all tests or mocking scenarios a class can be specified to initialize expectations in the MockServer, this class must implement org.mockserver.initialize.ExpectationInitializer interface, the initializeExpectations(MockServerClient mockServerClient) method will be called once the MockServer has been started (but ONLY if serverPort has been set), however it should be noted that it is generally better practice to create all expectations locally in each test (or test class) for clarity, simplicity and to avoid brittle tests. Note: that the plugin must be started during the process-test-classes to ensure that the initialization class has been compiled from either src/main/java or src/test/java locations. (required: false, default: false)
 

Client API  -  starting and stopping

Use the client API to run the MockServer programmatically.

First add the following maven dependency:

<!-- mockserver -->
<dependency>
     <groupId>org.mock-server</groupId>
     <artifactId>mockserver-netty</artifactId>
     <version>3.4</version>
</dependency>

To start the server and create a client the simplest way is to the start factory methods ClientAndServer.startClientAndServer or ClientAndProxy.startClientAndProxy as follows:

Add includes:

import static org.mockserver.integration.ClientAndProxy.startClientAndProxy;
import static org.mockserver.integration.ClientAndServer.startClientAndServer;

Add fields:

private ClientAndProxy proxy;
private ClientAndServer mockServer;

Use factory method to start server and client when appropriate, for example in @Before method:

@Before
public void startProxy() {
    mockServer = startClientAndServer(8080);
    proxy = startClientAndProxy(9090);
}

Stop server and client when appropriate, for example in @After method:

@After
public void stopProxy() {
    proxy.stop();
    mockServer.stop();
}

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

 

Running MockServer via a JUnit @Rule

MockServer can be run using the MockServerRule. The MockServerRule starts the MockServer on a free port before the any test runs and stops the MockServer after all tests have completed. A MockServerClient is then assigned to any field in the unit test of type org.mockserver.client.server.MockServerClient

@Rule
public MockServerRule mockServerRule = new MockServerRule(this);

private MockServerClient mockServerClient;

Any test method can now use the mockServerClient field to create expectation or verify requests.

The MockServerRule has the following constructors:

/**
 * Start the MockServer prior to test execution and stop the MockServer after the tests have completed.
 * This constructor dynamically allocates a free port for the MockServer to use.
 *
 * @param target an instance of the test being executed
 */
public MockServerRule(Object target);

/**
 * Start the MockServer prior to test execution and stop the MockServer after the tests have completed.
 * This constructor dynamically allocates a free port for the MockServer to use.
 *
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of MockServer are created
 *                     if true a single MockServer is created per JVM
 *                     if false one instance per test class is created
 */
public MockServerRule(Object target, boolean per TestSuite);
/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP requests on the specified port
 *
 * @param httpPort the HTTP port for the proxy
 * @param target an instance of the test being executed
 */
public MockServerRule(Integer httpPort, Object target);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP requests on the specified port
 *
 * @param httpPort the HTTP port for the proxy
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of MockServer are created
 *                     if true a single MockServer is created per JVM
 *                     if false one instance per test class is created
 */
public MockServerRule(Integer httpPort, Object target, boolean per TestSuite);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP and HTTPS requests on the specified ports
 *
 * @param httpPort the HTTP port for the proxy
 * @param httpsPort the HTTPS port for the proxy
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of MockServer are created
 *                     if true a single MockServer is created per JVM
 *                     if false one instance per test class is created
 */
public MockServerRule(Integer httpPort, Integer httpsPort, Object target, boolean per TestSuite);

The proxy can be run using the ProxyRule. The ProxyRule starts the proxy before the any test runs and stops the proxy after all tests have completed. A ProxyClient is then assigned to any field in the unit test of type org.mockserver.client.proxy.ProxyClient

@Rule
public ProxyRule proxyRule = new ProxyRule(8080, this);

private ProxyClient proxyClient;

Any test method can now use the proxyClient field to verify requests or anaylse a system's behaviour.

The ProxyRule has the following constructors:

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically allocates a free port for the proxy to use.
 * Note: The getHttpPort getter can be used to retrieve the dynamically allocated port.
 *
 * @param target an instance of the test being executed
 */
public ProxyRule(Object target);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically allocates a free port for the proxy to use.
 *
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of the proxy are created
 *                     if true a single proxy is created per JVM
 *                     if false one instance per test class is created
 */
public ProxyRule(Object target, boolean per TestSuite);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP requests on the specified port
 *
 * @param httpPort the HTTP port for the proxy
 * @param target an instance of the test being executed
 */
public ProxyRule(Integer httpPort, Object target);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP requests on the specified port
 *
 * @param httpPort the HTTP port for the proxy
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of the proxy are created
 *                     if true a single proxy is created per JVM
 *                     if false one instance per test class is created
 */
public ProxyRule(Integer httpPort, Object target, boolean per TestSuite);

/**
 * Start the proxy prior to test execution and stop the proxy after the tests have completed.
 * This constructor dynamically create a proxy that accepts HTTP and HTTPS requests on the specified ports
 *
 * @param httpPort the HTTP port for the proxy
 * @param httpsPort the HTTPS port for the proxy
 * @param target an instance of the test being executed
 * @param perTestSuite indicates how many instances of the proxy are created
 *                     if true a single proxy is created per JVM
 *                     if false one instance per test class is created
 */
public ProxyRule(Integer httpPort, Integer httpsPort, Object target, boolean per TestSuite);
 

Running From Command Line

MockServer can be run directly from the command line and using Embedded Jetty as follow:

  1. download mockserver-netty-3.4-jar-with-dependencies.jar from Maven Central

  2. java -jar <path to mockserver-netty-3.4-jar-with-dependencies.jar> -serverPort <port>

The command line supports the following options:

java -jar <path to jar> [-serverPort <port>]        \
                        [-serverSecurePort <port>]  \
                        [-proxyPort <port>]         \
                        [-proxySecurePort <port>]

  valid options are:
     -serverPort <port>         specifies the HTTP port for the MockServer
                                if neither serverPort or serverSecurePort
                                are provide the MockServer is not started
     -serverSecurePort <port>   specifies the HTTPS port for the MockServer
                                if neither serverPort or serverSecurePort
                                are provide the MockServer is not started

     -proxyPort <path>          specifies the HTTP port for the proxy
                                if neither proxyPort or proxySecurePort
                                are provide the MockServer is not started
     -proxySecurePort <path>    specifies the HTTPS port for the proxy
                                if neither proxyPort or proxySecurePort
                                are provide the MockServer is not started

For example:

java -jar ~/Downloads/mockserver-netty-3.4-jar-with-dependencies.jar -serverPort 8080 -proxyPort 9090
 

Docker Container

MockServer can be run as a Docker container.

First, you'll need to install Docker.

Then to run MockServer as a Docker container run the following command:

docker run -d -P jamesdbloom/mockserver

This command will map the ports exposed by the MockServer and Proxy to dynamic ports using the -P option. To specify which ports are used you can specify one or more port mappings using the -p <host port>:<container port> option. You only need to specify mapping for ports you need to use, for example, if you are not using the proxy there is no need to provide port mapping options for the proxy ports.

To run MockServer specifying as a Docker container run the following command (replacing each < ... > section with the appropriate port value):

docker run -d -p <serverPort>:8080 -p <serverSecurePort>:8090 -p <proxyPort>:9080 -p <proxySecurePort>:9090 jamesdbloom/mockserver

Note: you only need to specify mapping for ports you need to use, for example, if you are only using the MockServer to mock HTTP endpoints then only specify -p <serverPort>:8080 as follows (replacing each < ... > section with the appropriate port value):

docker run -d -p <serverPort>:8080 jamesdbloom/mockserver

This MockServer docker container exposes the following ports:

  • serverPort 8080
  • serverSecurePort 8090
  • proxyPort 9080
  • proxySecurePort 9090
 

Vert.X Module

MockServer can be run as a Vert.X module. However, support for the Vert.X module was stopped at version 2.9. This is because Vert.X requires Java 7 and the MockServer Vert.X module was the only MockServer module that relied on Java 7 making the build and development process more complex.

First, you'll need to install Vert.x.

Then to run MockServer as Vert.X module run the following command:

vertx install org.mock-server~mockserver-vertx~2.9
export VERTX_OPTS="-Dmockserver.serverPort=8080 -Dmockserver.serverSecurePort=1443 -Dmockserver.logLevel=TRACE"
vertx runmod org.mock-server~mockserver-vertx~2.9

The specify the HTTP port and / or HTTPS port the VERTX_OPTS environment variable must be set specifying the system property mockserver.serverPort for the HTTP port and mockserver.serverSecurePort for the HTTPS port.

Note: At least one of either the HTTP or the HTTPS port must be specified for the MockServer to run.

export VERTX_OPTS="-Dmockserver.serverPort=8080 -Dmockserver.serverSecurePort=1443 -Dmockserver.logLevel=TRACE"

It is also possible to update the default logging level by setting the system properties mockserver.logLevel as above.

 

Web Archive (WAR)

To run as a WAR deployed on any JEE web server:

  1. download mockserver-war-3.4.war from Maven Central
  2. deploy mockserver-war-3.4.war to any JEE web server

WAR Context Path

The WAR context path is ignored from all request matching except when matching on the full request url.

Therefore when setting up expectations or verifying requests it is recommended to only match on request path (and not url) when the deployed WAR has a context path to avoid a dependency between the test code and the context path.

The MockServerClient constructor includes an argument for the context path that the WAR has been deployed to, as follows:

public MockServerClient(String host, int port, String contextPath)
 

Build & Run From Source

MockServer is now only built using maven as the use of gradle caused problems with the Travis CI environment so the gradle build was removed.

First clone the repository as follows:

git clone https://github.com/jamesdbloom/mockservice.git
cd mockserver

Next build and run the project using maven.

Maven

To build an executable jar containing all dependencies run the following command:

mvn clean package

This will produce a jar file under the target directory called, as follows:

mockserver-netty/target/mockserver-netty-3.4-jar-with-dependencies.jar

Run the MockServer then using the executable jar as per the instruction above in Running From The Command Line

Create Client For Existing MockServer or Proxy

To create a pointing at an existing endpoint using the MockServerClient and ProxyClient constructors, for example:

@Before
public void startProxy() {
    mockServer = new MockServerClient("localhost", 8080);
    proxy = new ProxyClient("localhost", 9090);
}

The MockServerClient has the following methods:

/**
* Start the client communicating to a MockServer at the specified host and port
* for example:
*
*   MockServerClient mockServerClient = new MockServerClient("localhost", 8080);
*
* @param host the host for the MockServer to communicate with
* @param port the port for the MockServer to communicate with
*/
public MockServerClient(String host, int port);

/**
* Start the client communicating to a MockServer at the specified host and port
* and contextPath for example:
*
*   MockServerClient mockServerClient = new MockServerClient("localhost", 8080, "/mockserver");
*
* @param host the host for the MockServer to communicate with
* @param port the port for the MockServer to communicate with
* @param contextPath the context path that the MockServer war is deployed to
*/
public MockServerClient(String host, int port, String contextPath);

/**
* Specify an unlimited expectation that will respond regardless of the number of matching http
* for example:
*
*   mockServerClient
*           .when(
*                   request()
*                           .withPath("/some_path")
*                           .withBody("some_request_body")
*           )
*           .respond(
*                   response()
*                           .withBody("some_response_body")
*                           .withHeaders(
*                                   new Header("responseName", "responseValue")
*                           )
*           );
*
* or:
*   mockServerClient
*           .when(
*                   request()
*                           .withPath("/some_path")
*                           .withBody("some_request_body")
*           )
*           .forward(
*                   forward()
*                           .withHost("some_host_name")
*                           .withPort(80)
*           );
*
* @param httpRequest the http request that must be matched for this expectation to respond
* @return an Expectation object that can be used to specify the response
*/
public ForwardChainExpectation when(HttpRequest httpRequest);

/**
* Specify an limited expectation that will respond a specified number of times when the http is matched
* for example:
*
*   mockServerClient
*           .when(
*                   new HttpRequest()
*                           .withPath("/some_path")
*                           .withBody("some_request_body"),
*                   Times.exactly(5)
*           )
*           .respond(
*                   new HttpResponse()
*                           .withBody("some_response_body")
*                           .withHeaders(
*                                   new Header("responseName", "responseValue")
*                           )
*           );
*
* or:
*   mockServerClient
*           .when(
*                   request()
*                           .withPath("/some_path")
*                           .withBody("some_request_body"),
*                   Times.once()
*           )
*           .forward(
*                   forward()
*                           .withHost("some_host_name")
*                           .withPort(80)
*           );
*
* @param httpRequest the http request that must be matched for this expectation to respond
* @param times       the number of times to respond when this http is matched
* @return an Expectation object that can be used to specify the response
*/
public ForwardChainExpectation when(HttpRequest httpRequest, Times times);

/**
* Pretty-print the json for all expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*/
public MockServerClient dumpToLog();

/**
* Pretty-print the json for all expectations that match the request to the log.
* They are printed into a dedicated log called mockserver_request.log
*
* @param httpRequest the http request that is matched against when deciding what to log
*                    if null all requests are logged
*/
public MockServerClient dumpToLog(HttpRequest httpRequest);

/**
* Reset MockServer by clearing all expectations
*/
public MockServerClient reset();

/**
* Clear all expectations that match the http
*
* @param httpRequest the http request that is matched against when deciding whether to clear each expectation
*                    if null all expectations are cleared
*/
public MockServerClient clear(HttpRequest httpRequest);

The ProxyClient has the following methods:

/**
* Start the client communicating to the proxy at the specified host and port
* for example:
*   ProxyClient mockServerClient = new ProxyClient("localhost", 1080);
*
* @param host the host for the proxy to communicate with
* @param port the port for the proxy to communicate with
*/
public ProxyClient(String host, int port);

/**
* Pretty-print the json for all requests / responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*/
public ProxyClient dumpToLogAsJSON();

/**
* Pretty-print the json for matching requests and their responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*
* @param httpRequest the http request that is matched against when deciding what to log
*                    if null all requests are logged
*/
public ProxyClient dumpToLogAsJSON(HttpRequest httpRequest);

/**
* Output Java code for creating all requests / responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*/
public ProxyClient dumpToLogAsJava();

/**
* Output Java code for creating matching requests and their responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*
* @param httpRequest the http request that is matched against when deciding what to log
*                    if null all requests are logged
*/
public ProxyClient dumpToLogAsJava(HttpRequest httpRequest);

/**
* Reset the proxy by clearing recorded requests
*/
public ProxyClient reset();

/**
* Clear all recorded requests that match the httpRequest parameter
*
* @param httpRequest the http request that is matched against when deciding whether to clear recorded requests
*/
public ProxyClient clear(HttpRequest httpRequest);

/**
* Verify a request has been sent for example:
*
*   mockServerClient
*           .verify(
*                   request()
*                           .withPath("/some_path")
*                           .withBody("some_request_body")
*           );
*
* @param httpRequest the http request that must be matched for this verification to pass
* @throws AssertionError if the request has not been found
*/
public ProxyClient verify(HttpRequest httpRequest) throws AssertionError;

/**
* Verify a request has been sent for example:
*
*   mockServerClient
*           .verify(
*                   request()
*                           .withPath("/some_path")
*                           .withBody("some_request_body"),
*                   Times.exactly(3)
*           );
*
* @param httpRequest the http request that must be matched for this verification to pass
* @param times the number of times this request must be matched
* @throws AssertionError if the request has not been found
*/
public ProxyClient verify(HttpRequest httpRequest, Times times) throws AssertionError;

/**
* Retrieve the recorded requests that match the httpRequest parameter as expectations
*
* @param httpRequest the http request that is matched against when deciding whether to return each expectation,
*                    use null for the parameter to retrieve for all requests
* @return an array of all expectations that have been recorded by the proxy
*/
public Expectation[] retrieveAsExpectations(HttpRequest httpRequest);

/**
* Retrieve the recorded requests that match the httpRequest parameter as a JSON array
*
* @param httpRequest the http request that is matched against when deciding whether to return each expectation,
*                    use null for the parameter to retrieve for all requests
* @return a JSON array of all expectations that have been recorded by the proxy
*/
public String retrieveAsJSON(HttpRequest httpRequest);
 

Create Expectations

To create an expectation you need to define:

The 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 the 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", 8080)
        .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", 8080)
        .when(
                request()
                        .withMethod("GET")
                        .withPath("/index.html"),
                exactly(1)
        )
        .forward(
                forward()
                        .withHost("www.mock-server.com")
                        .withPort(80)
                        .withScheme(HTTP)
        );

Note: this requires the use of these static imports as follows:

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.matchers.Times.exactly; import static java.util.concurrent.TimeUnit.SECONDS; import static org.mockserver.model.HttpForward.Scheme.HTTP;

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

JavaScript

To setup an expectation that responds to a request:

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:8080/expectation", false);
xmlHttpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xmlHttpRequest.send(JSON.stringify({
    "httpRequest": {
        "method": "POST",
        "path": "/login",
        "queryStringParameters": [
            {
                "name": "returnUrl",
                "values": ["/account"]
            }
        ],
        "cookies": [
            {
                "name": "sessionId",
                "values": ["2By8LOhBmaW5nZXJwcmludCIlMDAzMW"]
            }
        ],
        "body": {
            "type": "EXACT"
            "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" }),
        "delay": {
            "timeUnit": "SECONDS",
            "value": 1
        }
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}));

To setup an expectation that forwards to a request:

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:8080/expectation", false);
xmlHttpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xmlHttpRequest.send(JSON.stringify({
    "httpRequest": {
        "method": "GET",
        "path": "/index.html"
    },
    "httpForward": {
        "host": "www.mock-server.com",
        "port": 80,
        "scheme": "HTTP"
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}));
 

Request Matcher

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:

  • url - regex or plain text
  • path - regex or plain text
  • query string - regex or plain text
  • headers - regex or plain text
  • cookies - regex or plain text
  • body - XPath, json, regex, plain text (exact match), or body parameters

The body can be matched using plain text, a json expression, an XPath expression or a regular expression, see XPath Expression Syntax for supported XPath syntax.

A json expressions is a valid json object. When a json expression is matched against a request body only fields in the json expression are matched, any extra fields in the request body not specified in the json expression will be ignored, in addition the order of fields in the body will be ignored.

All other matching can be done using plain text or a regular expression, see Pattern (Java Platform SE 7) for supported regular expression syntax.

Java

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 URL to match on such as "http://localhost:9999/some_mocked_path" regex values are also
     * supported such as ".*some_mocked_path", see http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
     * for full details of the supported regex syntax
     *
     * @param url the full URL such as "http://localhost:9999/some_mocked_path" or a regex
     */
    public HttpRequest withURL(String url);

    /**
     * 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/7/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 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/7/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/7/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/7/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/7/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);

    /**
     * The body to match on such as "this is an exact string body" or a json expression such as "{username: 'foo', password: 'bar'}" or a regex
     * (see http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html)
     * or an XPath expression which returns one or more values or evaluates to true
     * (see http://saxon.sourceforge.net/saxon6.5.3/expressions.html)
     *
     * @param body the body on such as "this is an exact string body"
     *             or a regex such as "username[a-z]{4}"
     *             or a json expression such as "{username: 'foo', password: 'bar'}"
     *             or an XPath such as "/element[key = 'some_key' and value = 'some_value']"
     */
    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("{username: 'foo', password: 'bar'}", Body.Type.EXACT)
     * exact match:
     *   - regex("username[a-z]{4}"); or
     *   - new StringBody("username[a-z]{4}", Body.Type.REGEX);
     * json match:
     *   - json("{username: 'foo', password: 'bar'}"); or
     *   - new StringBody("{username: 'foo', password: 'bar'}", Body.Type.JSON);
     * xpath match:
     *   - xpath("/element[key = 'some_key' and value = 'some_value']"); or
     *   - new StringBody("/element[key = 'some_key' and value = 'some_value']", Body.Type.XPATH);
     * 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")
     *     );
     *
     * for more details of the supported regex syntax see http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
     * for more details of the supported json syntax see http://jsonassert.skyscreamer.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/7/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/7/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/7/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);

    /**
     * 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/7/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/7/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/7/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);
}

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

To specify a request matcher in javascript use JSON to specify the details with the following format:

"httpRequest": {
    "method": "",
    "path": "",
    "queryParameters": []
    "body": {
       "type": <"EXACT" or "REGEX" or "JSON" 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.

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": "EXACT",
        "value": "{username: 'foo', password: 'bar'}"
    }
}

The "type" value in "body" can be:

"EXACT"
"REGEX"
"JSON"
"XPATH"
"PARAMETERS"

When the "type" field has a value of "EXACT", "REGEX", "JSON" 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.

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

Times

The org.mockserver.matchers.Times class is used to specify how many times you want the 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);
 

Mock Responses

Responses can 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)

Java

To mock a response in Java use the org.mockserver.model.HttpResponse class which specifies the details of each HTTP response with a fluent API:

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);

    /**
     * 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)

    /**
     * The response body
     *
     * @param body a "UTF-8" string
     */
    public HttpResponse withBody(String 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);
}

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));

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

Mock Forward

Forward configuration can 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 can be further controlled using:

  • the number of times the request is forwarded (including unlimited)

Java

To setup a forward in Java use the org.mockserver.model.HttpForward class which specifies the details of each HTTP(S) forward with a fluent API:

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);
}

For example:

HttpForward httpForward =
        forward()
                .withHost("www.mock-server.com")
                .withPort(80)
                .withScheme(HttpForward.Scheme.HTTP);

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

Verifying Behaviour

Request can be verified in two ways:

  • MockServer - the MockServer records all requests made to the MockServer and can be used to verify which requests have been made
  • Proxy - the proxy records all requests that are proxied and can be used to verify which requests have been made

MockServer Verification

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

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

Proxy Verification

In addition to verifying request that are being mocked by the MockServer it is also possible to verify requests not being mocked using the proxy. To do this the system under test must be configured to use the MockServer proxy. The following examples show how to do this with different HTTP clients.

Jetty HttpClient 9.x

HttpClient httpClient = new HttpClient();
try {
    httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", 9090));
    httpClient.start();
} catch (Exception e) {
    throw new RuntimeException("Exception creating HttpClient", e);
}

Jetty HttpClient 8.x

HttpClient httpClient = new HttpClient();
try {
    httpClient.setProxy(new Address("localhost", 9090));
    httpClient.start();
} catch (Exception e) {
    throw new RuntimeException("Exception creating HttpClient", e);
}

The mockserver-example project contains an example of using the proxy with Jetty HttpClient called BookServiceJettyHttpClient that demonstrates a fully working example.

Apache HttpClient

HttpHost httpHost = new HttpHost("localhost", 9090);
DefaultProxyRoutePlanner defaultProxyRoutePlanner = new DefaultProxyRoutePlanner(httpHost);
HttpClient httpClient = HttpClients.custom().setRoutePlanner(defaultProxyRoutePlanner).build();

The mockserver-example project contains an example of using the proxy with Apache HttpClient called BookServiceApacheHttpClient that demonstrates a fully working example.

Jersey

ClientConfig clientConfig = new ClientConfig().register(new JacksonFeature())
                                              .connectorProvider(new ApacheConnectorProvider());
clientConfig.property(ClientProperties.PROXY_URI, "http://localhost:9090");
Client client = ClientBuilder.newClient(clientConfig);

The mockserver-example project contains an example of using the proxy with Jersey called BookServiceJerseyClient that demonstrates a fully working example.

Spring Rest Template

RestTemplate restTemplate = new RestTemplate();
HttpHost httpHost = new HttpHost("localhost", 9090);
DefaultProxyRoutePlanner defaultProxyRoutePlanner = new DefaultProxyRoutePlanner(httpHost);
HttpClient httpClient = HttpClients.custom().setRoutePlanner(defaultProxyRoutePlanner).build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));

The mockserver-example project contains an example of using the proxy with Spring Rest Template called BookServiceSpringRestTemplateClient that demonstrates a fully working example.

Grizzly

AsyncHttpClientConfig.Builder clientConfigBuilder = new AsyncHttpClientConfig.Builder();
clientConfigBuilder.setProxyServerSelector(ProxyUtils.createProxyServerSelector(HttpProxy.proxySelector()));
AsyncHttpClient asyncHttpClient = new AsyncHttpClient(clientConfigBuilder.build());

The mockserver-example project contains an example of using the proxy with Grizzly Http Client called BookServiceGrizzlyHttpClient that demonstrates a fully working example.

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

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

The org.mockserver.client.proxy.Times class is used to specify how many times you want the MockServer to match a request:

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

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

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

 

Analysing Behaviour

To analyse the requests that system makes the proxy can be used to record all requests and write them into the mockserver_request.log. This can be particularly helpful when refactoring an existing or legacy system.

The requests can be written to the log in JSON or as Java code. The Java code can then be used to setup expectations in the MockServer and exactly replay all interactions.

First the system that is being analysed must be configured to use the proxy.

If the proxy is being started programmatically from within the same JVM using org.mockserver.proxy.ProxyRunner or org.mockserver.integration.ClientAndProxy then the environment variables for "proxySet", "http.proxyHost" and "http.proxyPort" will be set automatically.

If the proxy is being started as separate JVM, for example using the command line, then the system being analysed needs the following command line options to set the correct environment variables.

-DproxySet=true -Dhttp.proxyHost=<proxy hostname> -Dhttp.proxyPort=<proxy port>

For example:

-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=9090

Apache HttpClient

To configure the proxy with an Apache HttpClient, as follows:

public HttpClient createHttpClient() {
    if (Boolean.parseBoolean(System.getProperty("proxySet"))) {
        HttpHost httpHost = new HttpHost(System.getProperty("http.proxyHost"), Integer.parseInt(System.getProperty("http.proxyPort")));
        DefaultProxyRoutePlanner defaultProxyRoutePlanner = new DefaultProxyRoutePlanner(httpHost);
        return HttpClients.custom().setRoutePlanner(defaultProxyRoutePlanner).build();
    } else {
        return HttpClients.custom().build();
    }
}

The mockserver-example project contains an example of using the proxy with a Apache HttpClient called BookServiceApacheHttpClient that demonstrates a fully working example.

Grizzly AsyncHttpClient

To configure the proxy with a Grizzly AsyncHttpClient, as follows:

public AsyncHttpClient createHttpClient() {
    AsyncHttpClientConfig.Builder clientConfigBuilder = new AsyncHttpClientConfig.Builder();
    if (Boolean.parseBoolean(System.getProperty("proxySet"))) {
        clientConfigBuilder.setProxyServerSelector(ProxyUtils.createProxyServerSelector(ProxyRunner.proxySelector()));
    }
    return new AsyncHttpClient(clientConfigBuilder.build());
}

The mockserver-example project contains an example of using the proxy with a Grizzly AsyncHttpClient called BookServiceGrizzlyHttpClient that demonstrates a fully working example.

Jersey Client

To configure the proxy with a Jersey Client, as follows:

public Client createHttpClient() {
    ClientConfig clientConfig = new ClientConfig()
            .register(new JacksonFeature())
            .connectorProvider(new ApacheConnectorProvider());
    if (Boolean.parseBoolean(System.getProperty("proxySet"))) {
        clientConfig.property(ClientProperties.PROXY_URI, "http://" + System.getProperty("http.proxyHost") + ":" + System.getProperty("http.proxyPort"));
    }
    return ClientBuilder.newClient(clientConfig);
}

The mockserver-example project contains an example of using the proxy with a Jersey Client called BookServiceJerseyClient that demonstrates a fully working example.

Jetty HttpClient

To configure the proxy with a Jetty HttpClient, as follows:

public HttpClient createHttpClient() {
    HttpClient httpClient = new HttpClient();
    try {
        if (Boolean.parseBoolean(System.getProperty("proxySet"))) {
            httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(System.getProperty("http.proxyHost"), Integer.parseInt(System.getProperty("http.proxyPort"))));
        }
        httpClient.start();
    } catch (Exception e) {
        throw new RuntimeException("Exception creating HttpClient", e);
    }
    return httpClient;
}

The mockserver-example project contains an example of using the proxy with a Jetty HttpClient called BookServiceJettyHttpClient that demonstrates a fully working example.

Spring RestTemplate

To configure the proxy with a Spring RestTemplate, as follows:

public RestTemplate createRestTemplate() {
    // jackson message converter
    MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
    mappingJacksonHttpMessageConverter.setObjectMapper(objectMapper);

    // create message converters list
    List<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>();
    httpMessageConverters.add(mappingJacksonHttpMessageConverter);

    // create rest template
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setMessageConverters(httpMessageConverters);

    // configure proxy
    if (Boolean.parseBoolean(System.getProperty("proxySet"))) {
        HttpHost httpHost = new HttpHost(
                System.getProperty("http.proxyHost"),
                Integer.parseInt(System.getProperty("http.proxyPort"))
        );
        DefaultProxyRoutePlanner defaultProxyRoutePlanner = new DefaultProxyRoutePlanner(httpHost);
        HttpClient httpClient = HttpClients.custom().setRoutePlanner(defaultProxyRoutePlanner).build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }

    return restTemplate;
}

The mockserver-example project contains an example of using the proxy with a Spring RestTemplate called BookServiceSpringRestTemplateClient that demonstrates a fully working example.

Write Requests To Log

Write the recorded request to the log as Java code, as follows:

new ProxyClient("localhost", 9090).dumpToLogAsJava(
        request()
                .withMethod("POST")
                .withPath("/login")
);

The Java code format that requests are written to the logs is as follows:

2014-01-12 21:46:33,305
new MockServerClient()
        .when(
                request()
                        .withMethod("GET")
                        .withURL("http://localhost:8080/get_book?id=1")
                        .withPath("/get_book")
                        .withQueryString("id=1")
                        .withHeaders(
                                new Header("Accept-Encoding", "gzip"),
                                new Header("Host", "localhost:1090"),
                                new Header("User-Agent", "Jetty/8.1.13.v20130916")
                        ),
                Times.once()
        )
        .thenRespond(
                response()
                        .withStatusCode(200)
                        .withHeaders(
                                new Header("Server", "Jetty(8.1.13.v20130916)")
                        )
                        .withBody("{\n        \"id\": \"1\",\n        \"title\": \"Xenophon's imperial fiction : on the education of Cyrus\",\n        \"author\": \"James Tatum\",\n        \"isbn\": \"0691067570\",\n        \"publicationDate\": \"1989\"\n    }")
        );

Write the recorded request to the log as JSON, as follows:

new ProxyClient("localhost", 9090).dumpToLogAsJSON(
        request()
                .withMethod("POST")
                .withPath("/login")
);

The JSON format that requests are written to the logs is as follows:

2014-01-12 21:46:33,299 {
    "httpRequest" : {
        "method" : "GET",
        "url" : "http://localhost:8080/get_book?id=1",
        "path" : "/get_book",
        "queryString" : "id=1",
        "headers" : [
            {
                "name" : "Accept-Encoding",
                "values" : [ "gzip" ]
            },
            {
                "name" : "Host",
                "values" : [ "localhost:8080" ]
            },
            {
                "name" : "User-Agent",
                "values" : [ "Jetty/8.1.13.v20130916" ]
            } ]
    },
    "httpResponse" : {
        "statusCode" : 200,
        "body" : "{\n    \"id\": \"1\",\n    \"title\": \"Xenophon's imperial fiction : on the education of Cyrus\",\n    \"author\": \"James Tatum\",\n    \"isbn\": \"0691067570\",\n    \"publicationDate\": \"1989\"\n}",
        "headers" : [ {
            "name" : "Server",
            "values" : [ "Jetty(8.1.13.v20130916)" ]
        } ]
    },
    "times" : {
        "remainingTimes" : 1,
        "unlimited" : false
    }
}
 

Running Tests In Parallel

To ensure all tests can run in parallel with completely isolated independent data it is important to include a value unique to each test for the request matcher.

For example the code above has a sessionId cookie in the request matcher. If each test generates a different value (i.e. a UUID) for the sessionId cookie then each test can receive completely independent response. Instead of a cookie value a query parameter or header (such as the Referer header) can also be used to ensure mock responses are unique to each test.

 

Clear & Reset

To clear all expectations (without restarting) use reset as follows:

Java

mockServerClient.reset()

JavaScript

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:9999/reset", false);
xmlHttpRequest.send();

To clear only specific expectations use clear as follows:

Java

mockServerClient.clear(
        request()
                .withMethod("POST")
                .withPath("/login")
);

JavaScript

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:9999/clear", false);
xmlHttpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xmlHttpRequest.send(JSON.stringify({
    "method": "POST",
    "path": "/login",
}));

The example above clears all expectations that will match incoming requests with a POST method on the path /login.

 

Debugging Issues

To simplify debugging the MockServer expectations can be dumped to the log at WARN level using pretty-printed JSON.

To dump all expectations to the log use dumpToLog as follows:

Java

mockServerClient.dumpToLog()

JavaScript

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:9999/dumpToLog", false);
xmlHttpRequest.send();

To dump only specific expectations to the log use dumpToLog as follows:

Java

mockServerClient.dumpToLog(
        request()
                .withMethod("POST")
                .withPath("/login")
);

JavaScript

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("PUT", "http://localhost:9999/dumpToLog", false);
xmlHttpRequest.send(JSON.stringify({
    "method": "POST",
    "path": "/login",
}));

The example above dumps all expectations that match incoming requests with a POST method on the path /login.

 

Requirements

  • Java 6+   to use the Netty version, the Maven Plugin and MockServer WAR and proxy WAR
  • Java 7+   to use the Vert.X module or the Embedded Jetty version as both Jetty 9 and Vert.X in turn require Java 7 (Note: all features provided in the Embedded Jetty version are also available using the Netty version)
 

Downloads

The simplest way to run and download MockServer is by using the fully stand alone web server embedded with all dependencies that mocks HTTP and HTTPS requests, as follows:

  1. download mockserver-netty-3.4-jar-with-dependencies.jar from Maven Central

  2. java -jar <path to mockserver-netty-3.4-jar-with-dependencies.jar> -serverPort <port>

For more details on downloads see:

 

GitHub

The source control for MockServer is git which is hosted at GitHub jamesdbloom/mockserver

GitHub is also used to track issues / bugs and manage pull-requests.

 

Maven Central

Maven Central contains the following MockServer artifacts:

In addition MockServer SNAPSHOT artifacts can also be found at https://oss.sonatype.org/index.html#nexus-search;quick~mockserver.

 

Ruby Gems

Ruby Gems contains the following gems:

 

Vert.X Module Registry

Vert.X Module Registry contains the following artifacts:

Vert.X Module Registry will shortly also have the following artifacts:

 

Docker Container

MockServer is available as a docker container that allows you to easily run MockServer as a separate container on any environment without having to install Java or any other libraries. The docker container fully encapsulates all requirements required to run MockServer (such as Java) and separates the running MockServer instance from all other parts of the system.

The MockServer docker container can be found at MockServer Docker

 

Travis CI

Travis CI is used for the continuous integration. The build uses both Java 1.6, Java 1.7 and Java 1.8 to build the different modules in their appropriate java version, the latest SNAPSHOT is also deployed to Sonatype.

The status of the build is shown at the top of this page and on the github project using the Travis CI logo   Build Status

drone.io

drone.io is an alternative continuous integration platform also being used. Currently Travis CI, drone.io and Codeship are all being used to determine which platform works better for MockServer.

The status of the drone.io build is as follows: Build Status

Codeship

Codeship is an alternative continuous integration platform also being used. Currently Travis CI, drone.io and Codeship are all being used to determine which platform works better for MockServer.

The status of the Codeship build is as follows: Codeship Build Status

 

Backlog

Waffle is used to visualise the backlog, although all the items are stored in Github.

The following icons shows the status of the backlog: Stories in Backlog Stories in Backlog Stories in Backlog


James D Bloom - Blog