Note: this page is a high level overview of each topic, more detail is available for each topic on a linked page.

The typical sequence for using MockServer is as follows:

  1. Start MockServer
  2. Setup Expectations
  3. Run Your Test Scenarios
  4. Verify Requests

Mocking service dependencies with MockServer

For example code see the code examples folder in the git repository.

 

0. Start MockServer

MockServer is flexible and support numerous usage patterns.

MockServer can be run:

To simplify configuration all versions (except the deployable WAR) use a single port to support the control plane and data plane in HTTP, HTTPS or SOCKS.

MockServer is available in the following formats:

It is also possible to build and run MockServer directly from source code

MockServer UI:

MockServer has a UI that can be used to view the internal state within MockServer, including:

 

1. Setup Expectations

Please Note: There are over 100 more detailed code examples in Java, JavaScript and the REST API below.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("POST")
            .withPath("/login")
            .withBody("{username: 'foo', password: 'bar'}")
    )
    .respond(
        response()
            .withStatusCode(302)
            .withCookie(
                "sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
            )
            .withHeader(
                "Location", "https://www.mock-server.com"
            )
    );

Please Note: There are over 100 more detailed code examples in Java, JavaScript and the REST API below.

var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "POST",
        "path": "/login",
        "body": {
            "username": "foo",
            "password": "bar"
        }
    },
    "httpResponse": {
        "statusCode": 302,
        "headers": {
            "Location": [
                "https://www.mock-server.com"
            ]
        },
        "cookies": {
            "sessionId": "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

To use the Java client add the org.mock-server:mockserver-client-java-no-dependencies:6.1.0 dependency. The -no-dependencies artifact bundles all dependencies with relocated packages, so it declares zero transitive dependencies — this avoids classpath conflicts and CVE scanning noise from unused transitive dependencies.

For more details about the different dependency versions see the page on Maven Central

for example in maven:

<dependency>
	<groupId>org.mock-server</groupId>
	<artifactId>mockserver-client-java-no-dependencies</artifactId>
	<version>6.1.0</version>
</dependency>

A request matcher expectation may contain:

  • request matcher - used to match which requests this expectation should be applied to
  • action - what action to take, actions include response, forward, callback and error
  • times (optional) - how many times the action should be taken
  • timeToLive (optional) - how long the expectation should stay active
  • priority (optional) - matching is ordered by priority (highest first) then creation (earliest first)
  • id (optional) - used for updating an existing expectation (i.e. when the id matches)
  • scenario (optional) - used for stateful multi-step API flows where the response changes based on prior interactions
  • httpResponses (optional) - an array of responses to cycle through sequentially or randomly on each match

open api expectations are also supported using an OpenAPI v3 specifications to generate request matcher expectations for each operation, see the section on open api expectations for details.

 

Matching Order

MockServer will match (or play) active expectations in the exact order they are added (if their priority is identical). For example, if an expectation A is added with Times.exactly(3) then expectation B is added with Times.exactly(2) with the same request matcher they will be applied in the following order A, A, A, B, B. Priority can be used to alter the order that expectations are matched; matching is ordered by priority (highest first) then creation (earliest first).

Priority can be used to configure a default expectation or response by specifying a negative value for priority and a very lax request matcher; the lax request matcher ensures the default expectation is always matched, but the low priority ensure it is matched last after all other expectations.

 

Probabilistic Matching (Percentage)

An expectation can be configured with a percentage (0-100) to enable probabilistic matching. When set, the expectation will only match the specified percentage of requests that structurally match the request matcher. This is useful for simulating intermittent failures, flaky services, or A/B testing scenarios.

For example, setting percentage to 50 means approximately half of matching requests will be handled by this expectation, while the other half will fall through to the next matching expectation or the default behavior.

If percentage is not set or set to 100, the expectation matches all structurally matching requests (the default behavior). A value of 0 means the expectation never matches.

 

Stateful Scenarios

Stateful scenarios let you model multi-step API conversations where MockServer's response changes based on prior interactions. Each scenario is an independent named state machine that starts in the "Started" state.

An expectation can participate in a scenario by specifying:

  • scenarioName - the name of the scenario this expectation belongs to
  • scenarioState - the state the scenario must be in for this expectation to match
  • newScenarioState - the state the scenario transitions to after this expectation matches

If scenarioName is not set, the expectation behaves normally without any scenario filtering. The default initial state for all scenarios is "Started".

Example - Login Flow: First call returns a token, subsequent calls using that token get a different response.

// Step 1: Login returns a token (scenario starts in "Started" state)
{
    "httpRequest": {
        "method": "POST",
        "path": "/login"
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"token\": \"abc123\"}"
    },
    "scenarioName": "LoginFlow",
    "scenarioState": "Started",
    "newScenarioState": "LoggedIn",
    "times": { "remainingTimes": 1 }
}

// Step 2: After login, GET /profile returns user data
{
    "httpRequest": {
        "method": "GET",
        "path": "/profile"
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"name\": \"Alice\", \"email\": \"alice@example.com\"}"
    },
    "scenarioName": "LoginFlow",
    "scenarioState": "LoggedIn"
}

// Step 3: Before login, GET /profile returns 401
{
    "httpRequest": {
        "method": "GET",
        "path": "/profile"
    },
    "httpResponse": {
        "statusCode": 401,
        "body": "{\"error\": \"Not authenticated\"}"
    },
    "scenarioName": "LoginFlow",
    "scenarioState": "Started"
}

Example - Pagination: Successive calls to the same endpoint return different pages of data.

// Page 1 (initial state)
{
    "httpRequest": {
        "method": "GET",
        "path": "/items"
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"items\": [\"a\", \"b\"], \"page\": 1, \"hasMore\": true}"
    },
    "scenarioName": "Pagination",
    "scenarioState": "Started",
    "newScenarioState": "Page2",
    "times": { "remainingTimes": 1 }
}

// Page 2
{
    "httpRequest": {
        "method": "GET",
        "path": "/items"
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"items\": [\"c\", \"d\"], \"page\": 2, \"hasMore\": true}"
    },
    "scenarioName": "Pagination",
    "scenarioState": "Page2",
    "newScenarioState": "Page3",
    "times": { "remainingTimes": 1 }
}

// Page 3 (last page)
{
    "httpRequest": {
        "method": "GET",
        "path": "/items"
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"items\": [\"e\"], \"page\": 3, \"hasMore\": false}"
    },
    "scenarioName": "Pagination",
    "scenarioState": "Page3"
}

Example - Retry Testing: First two calls return 503, third call succeeds.

// First call: 503
{
    "httpRequest": { "path": "/api/data" },
    "httpResponse": { "statusCode": 503, "body": "{\"error\": \"Service Unavailable\"}" },
    "scenarioName": "RetryTest",
    "scenarioState": "Started",
    "newScenarioState": "Attempt2",
    "times": { "remainingTimes": 1 }
}

// Second call: 503
{
    "httpRequest": { "path": "/api/data" },
    "httpResponse": { "statusCode": 503, "body": "{\"error\": \"Service Unavailable\"}" },
    "scenarioName": "RetryTest",
    "scenarioState": "Attempt2",
    "newScenarioState": "Ready",
    "times": { "remainingTimes": 1 }
}

// Third call onwards: 200
{
    "httpRequest": { "path": "/api/data" },
    "httpResponse": { "statusCode": 200, "body": "{\"data\": \"success\"}" },
    "scenarioName": "RetryTest",
    "scenarioState": "Ready"
}

Example - Order State Machine: Model an order lifecycle with state transitions.

// Create order
{
    "httpRequest": { "method": "POST", "path": "/orders" },
    "httpResponse": { "statusCode": 201, "body": "{\"id\": 1, \"status\": \"CREATED\"}" },
    "scenarioName": "OrderLifecycle",
    "scenarioState": "Started",
    "newScenarioState": "OrderCreated",
    "times": { "remainingTimes": 1 }
}

// Pay for order (only available after creation)
{
    "httpRequest": { "method": "PUT", "path": "/orders/1/pay" },
    "httpResponse": { "statusCode": 200, "body": "{\"id\": 1, \"status\": \"PAID\"}" },
    "scenarioName": "OrderLifecycle",
    "scenarioState": "OrderCreated",
    "newScenarioState": "OrderPaid",
    "times": { "remainingTimes": 1 }
}

// Get order - returns CREATED status
{
    "httpRequest": { "method": "GET", "path": "/orders/1" },
    "httpResponse": { "statusCode": 200, "body": "{\"id\": 1, \"status\": \"CREATED\"}" },
    "scenarioName": "OrderLifecycle",
    "scenarioState": "OrderCreated"
}

// Get order - returns PAID status
{
    "httpRequest": { "method": "GET", "path": "/orders/1" },
    "httpResponse": { "statusCode": 200, "body": "{\"id\": 1, \"status\": \"PAID\"}" },
    "scenarioName": "OrderLifecycle",
    "scenarioState": "OrderPaid"
}

Example - Rate Limiting: Allow a fixed number of calls, then return 429.

// First 3 calls succeed
{
    "httpRequest": { "path": "/api/resource" },
    "httpResponse": { "statusCode": 200, "body": "{\"data\": \"ok\"}" },
    "scenarioName": "RateLimit",
    "scenarioState": "Started",
    "newScenarioState": "Call2",
    "times": { "remainingTimes": 1 }
}
{
    "httpRequest": { "path": "/api/resource" },
    "httpResponse": { "statusCode": 200, "body": "{\"data\": \"ok\"}" },
    "scenarioName": "RateLimit",
    "scenarioState": "Call2",
    "newScenarioState": "Call3",
    "times": { "remainingTimes": 1 }
}
{
    "httpRequest": { "path": "/api/resource" },
    "httpResponse": { "statusCode": 200, "body": "{\"data\": \"ok\"}" },
    "scenarioName": "RateLimit",
    "scenarioState": "Call3",
    "newScenarioState": "RateLimited",
    "times": { "remainingTimes": 1 }
}

// Subsequent calls: 429 Too Many Requests
{
    "httpRequest": { "path": "/api/resource" },
    "httpResponse": { "statusCode": 429, "body": "{\"error\": \"Rate limit exceeded\"}" },
    "scenarioName": "RateLimit",
    "scenarioState": "RateLimited"
}
 

Example - Multi-Turn LLM Conversation: Script a two-turn agent loop where the model first calls a tool, then answers after receiving the tool result. Each turn advances the scenario state automatically. Use isolateBy so concurrent sessions (identified by a header, query parameter, or cookie) maintain independent state.

import static org.mockserver.client.LlmConversationBuilder.conversation;
import static org.mockserver.model.Completion.completion;
import static org.mockserver.model.ToolUse.toolUse;
import static org.mockserver.llm.IsolationSource.header;

conversation()
    .withPath("/v1/messages")
    .withProvider(Provider.ANTHROPIC)
    .withModel("claude-sonnet-4")
    .isolateBy(header("x-session-id"))
    .turn()
        .whenTurnIndex(0)
        .respondingWith(
            completion()
                .withToolCall(toolUse("search").withArguments("{\"query\":\"weather\"}"))
                .withStopReason("tool_use"))
    .andThen()
    .turn()
        .whenContainsToolResultFor("search")
        .respondingWith(
            completion()
                .withText("Based on the search results, it will be sunny.")
                .withStopReason("end_turn"))
    .applyTo(mockServerClient);

JSON equivalent (two expectations sharing a scenario):

// Turn 1: tool call
{
    "httpRequest": { "method": "POST", "path": "/v1/messages" },
    "httpLlmResponse": {
        "provider": "ANTHROPIC",
        "model": "claude-sonnet-4",
        "completion": {
            "toolCalls": [{ "name": "search", "arguments": "{\"query\":\"weather\"}" }],
            "stopReason": "tool_use"
        },
        "conversationPredicates": { "turnIndex": 0 }
    },
    "scenarioName": "__llm_conv_example",
    "scenarioState": "Started",
    "newScenarioState": "turn_1"
}

// Turn 2: final answer after tool result
{
    "httpRequest": { "method": "POST", "path": "/v1/messages" },
    "httpLlmResponse": {
        "provider": "ANTHROPIC",
        "model": "claude-sonnet-4",
        "completion": {
            "text": "Based on the search results, it will be sunny.",
            "stopReason": "end_turn"
        },
        "conversationPredicates": { "containsToolResultFor": "search" }
    },
    "scenarioName": "__llm_conv_example",
    "scenarioState": "turn_1",
    "newScenarioState": "__done"
}

Scenarios are independent of each other — different scenario names maintain separate state. All scenario states are reset when MockServer is reset.

 

Sequential / Cycling Responses

A single expectation can return multiple different responses by providing an array of responses in the httpResponses field. Each time the expectation matches, the next response in the list is returned. After the last response, it cycles back to the first.

The responseMode field controls how responses are selected:

  • SEQUENTIAL (default) - responses are returned in order, cycling back to the first after the last
  • RANDOM - a random response is selected from the list for each request

Note: Use httpResponses instead of httpResponse (singular) when you want multiple responses. If both are set, httpResponses takes priority.

Example - Sequential Responses: Cycle through different status codes.

{
    "httpRequest": {
        "path": "/api/status"
    },
    "httpResponses": [
        { "statusCode": 200, "body": "{\"status\": \"ok\"}" },
        { "statusCode": 503, "body": "{\"status\": \"degraded\"}" },
        { "statusCode": 200, "body": "{\"status\": \"ok\"}" }
    ]
}

The first request returns 200, the second returns 503, the third returns 200, then it cycles back to the first response.

Example - Random Responses: Simulate unpredictable service behavior.

{
    "httpRequest": {
        "path": "/api/unstable"
    },
    "httpResponses": [
        { "statusCode": 200, "body": "{\"result\": \"success\"}" },
        { "statusCode": 500, "body": "{\"error\": \"Internal Server Error\"}" },
        { "statusCode": 429, "body": "{\"error\": \"Too Many Requests\"}" }
    ],
    "responseMode": "RANDOM"
}

Example - Java Client:

import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

new MockServerClient("localhost", 1080)
    .when(request().withPath("/api/status"))
    .respond(
        java.util.Arrays.asList(
            response().withStatusCode(200).withBody("{\"status\": \"ok\"}"),
            response().withStatusCode(503).withBody("{\"status\": \"degraded\"}")
        )
    );
 

Updating Expectations

If an expectation is added and the id field matches an existing expectation the existing expectation will be updated (i.e. replaced). A UUID will be used assigned to each expectation if no value for id is specified.

 

Request Matchers

There are two types of request matcher:

 

A request properties matcher matches requests using one or more of the following properties:

 

Matching for properties can be done using:

  • string value
  • regex value
  • json schema
  • optional value
    • use for: method, path, path parameters values, query parameter keys, query parameters values, header keys, header values, cookie keys, cookie values or bodies
    • not supported for: path parameter keys
    • examples: query parameters, headers, cookies
  • negated value
    • use for: method, path, path parameter keys, path parameters values, query parameter keys, query parameters values, header keys, header values, cookie keys, cookie values or bodies
    • examples: method, path, headers
 

Note: path values containing { or } characters (such as /api/{id}) are interpreted as regex patterns, not literal strings. This is a common source of unexpected matching behaviour when path templates are used. To match literal curly braces in a path, use one of the following approaches:

  • Use an explicit regex matcher and escape the braces: withPath(regex("/api/\\{id\\}"))
  • Use an exact string matcher: withPath(exact("/api/{id}"))
 

Matching for key to multiple values supports multiple values for each key for headers, query parameters and path parameters

  • Keys support all property matcher except json schema
  • Values support all property matcher except optional values
  • Matching supports two modes:
    • sub set (default) - matches if the request property contains a matching sub set (considering optional keys), therefore there is at least one matching value for each non-optional key or optional key if present
    • matching key - matches if the request property contains only matching values (considering optional keys), therefore all values must match for each non-optional key or optional key if present

Note: for query parameters, the default sub set matching mode means that extra query parameters not specified in the matcher are allowed and do not cause a match failure. To enforce strict matching where only the specified query parameters are allowed (and any additional parameters cause a mismatch), use KeyMatchStyle.MATCHING_KEY on the request matcher. For example:

request()
    .withPath("/some/path")
    .withQueryStringParameters(
        new Parameters(
            param("key", "value")
        ).withKeyMatchStyle(KeyMatchStyle.MATCHING_KEY)
    )
 

Matching for key to single value supports a single value for each key for cookies

   

Important: when matching JSON bodies, there is a significant difference between plain string matching and semantic JSON matching:

  • withBody("{\"key\": \"value\"}") performs a character-by-character string comparison. This means whitespace, key ordering, and formatting must match exactly. For example, {"key":"value"} would not match {"key": "value"} because of the missing space.
  • withBody(json("{\"key\": \"value\"}")) performs a semantic JSON comparison. This ignores whitespace and (with ONLY_MATCHING_FIELDS) allows additional fields. Use this for matching JSON payloads.

If your expectations are not matching JSON requests as expected, ensure you are using json() rather than passing the JSON string directly.

Matching for bodies can be done using:

  • plain text (i.e. exact match)
  • regular expression - see Java regex syntax
  • JSON - supports:
    • matchType to control which fields get matched:
      • STRICT matches all fields, order of arrays and no additional fields allowed
      • ONLY_MATCHING_FIELDS only matches fields provided in the request matcher
    • matchNumbersAsStrings (optional, default false) if true, numeric values are compared by numeric value regardless of type, so 1, 1.0 and 1.00 are all considered equal. This is useful when different languages or serializers produce different numeric representations for the same value (e.g. Java sends 1.0 while Groovy sends 1).
    • JSONUnit placeholders to allow fields or values to be ignored or matched by type or pattern, for example:
      • ${json-unit.ignore-element} ignore a field
      • ${json-unit.any-boolean} match a field as any boolean
      • ${json-unit.any-string} match a field as any string
      • ${json-unit.any-number} match a field as any number
      • ${json-unit.regex}pattern match a field by regex, e.g. ${json-unit.regex}[a-z]+
      • ${json-unit.matches:name} match a field with a user-registered custom matcher (e.g. ${json-unit.matches:largerThan}); register the matcher by setting the mockserver.customJsonUnitMatchersClass configuration property to a class implementing CustomJsonUnitMatcherProvider
      see JSONUnit documentation for full details
  • JSON Schema - see JSON Schema documentation
  • JsonPath - matches if at least one value is returned by the expression, see JsonPath documentation
  • XML - supports:
    • XMLUnit placeholders to allow fields or elements to be ignored or matched by type for example:
      • ${xmlunit.ignore} ignore an element
      • ${xmlunit.isNumber} match an element or attribute as a number
      see XMLUnit documentation for full details
  • XML Schema - see XML Schema documentation
  • XPath - matches if at least one value returned by expression, see XPath specification
  • form fields (i.e. body parameters)
  • binary
  • GraphQL - whitespace-insensitive matching of GraphQL queries, mutations, and subscriptions
  • negated matcher
 

GraphQL Body Matching

MockServer supports whitespace-insensitive matching of GraphQL over HTTP JSON request bodies. This allows expectations to match GraphQL queries, mutations, and subscriptions regardless of whitespace, formatting, or comment differences. The request body must be a JSON object with a query field (the standard GraphQL over HTTP format).

A GraphQL body matcher can specify:

  • query (required) - the GraphQL query string. Whitespace is normalized before comparison, so { user { name } } matches {\n user {\n name\n }\n}
  • operationName (optional) - match the operation name exactly, or using a regex pattern (e.g. Get.*)
  • variablesSchema (optional) - a JSON Schema to validate the variables field

Example - match a GraphQL query:

{
    "httpRequest": {
        "method": "POST",
        "path": "/graphql",
        "body": {
            "type": "GRAPHQL",
            "query": "{ user(id: 1) { name email } }"
        }
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"data\": {\"user\": {\"name\": \"Alice\", \"email\": \"alice@example.com\"}}}"
    }
}

Example - match with operation name and variables schema:

{
    "httpRequest": {
        "method": "POST",
        "path": "/graphql",
        "body": {
            "type": "GRAPHQL",
            "query": "query GetUser($id: ID!) { user(id: $id) { name email } }",
            "operationName": "GetUser",
            "variablesSchema": "{\"type\": \"object\", \"properties\": {\"id\": {\"type\": \"string\"}}, \"required\": [\"id\"]}"
        }
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"data\": {\"user\": {\"name\": \"Alice\", \"email\": \"alice@example.com\"}}}"
    }
}

Example - match a mutation:

{
    "httpRequest": {
        "method": "POST",
        "path": "/graphql",
        "body": {
            "type": "GRAPHQL",
            "query": "mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name } }",
            "operationName": "CreateUser"
        }
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{\"data\": {\"createUser\": {\"id\": \"123\", \"name\": \"Alice\"}}}"
    }
}

The following code examples show how to match against different elements of a request using different matchers. For more examples see the code examples folder in the git repository.

For brevity static imports have not been included in the Java code examples so please add the following static imports if copying this code

import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path"),
        Times.once(),
        TimeToLive.exactly(TimeUnit.SECONDS, 60L),
        10
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    },
    "timeToLive": {
        "timeUnit": "SECONDS",
        "timeToLive": 60,
        "unlimited": false
    },
    "priority" : 10
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  },
  "times" : {
    "remainingTimes" : 1,
    "unlimited" : false
  },
  "timeToLive" : {
    "timeUnit" : "SECONDS",
    "timeToLive" : 60,
    "unlimited" : false
  },
  "priority" : 10
}'

See REST API for full JSON specification

A negative priority can be used to specify a default expectation or response.

new MockServerClient("localhost", 1080)
    .when(
        request(),
        Times.once(),
        TimeToLive.exactly(TimeUnit.SECONDS, 60L),
        -10
    )
    .respond(
        response()
            .withBody("some_default_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {},
    "httpResponse": {
        "body": "some_default_response_body"
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    },
    "timeToLive": {
        "timeUnit": "SECONDS",
        "timeToLive": 60,
        "unlimited": false
    },
    "priority" : -10
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {},
  "httpResponse" : {
    "body" : "some_default_response_body"
  },
  "times" : {
    "remainingTimes" : 1,
    "unlimited" : false
  },
  "timeToLive" : {
    "timeUnit" : "SECONDS",
    "timeToLive" : 60,
    "unlimited" : false
  },
  "priority" : -10
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path"),
        Times.exactly(2)
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    },
    "times": {
        "remainingTimes": 2
    },
    "timeToLive": {
        "unlimited": true
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  },
  "times" : {
    "remainingTimes" : 2,
    "unlimited" : false
  },
  "timeToLive" : {
    "unlimited" : true
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path"),
        Times.once(),
        TimeToLive.exactly(TimeUnit.SECONDS, 60L)
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    },
    "timeToLive": {
        "timeUnit": "SECONDS",
        "timeToLive": 60,
        "unlimited": false
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  },
  "times" : {
    "remainingTimes" : 1,
    "unlimited" : false
  },
  "timeToLive" : {
    "timeUnit" : "SECONDS",
    "timeToLive" : 60,
    "unlimited" : false
  }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches any requests those path starts with "/some"
            .withPath("/some.*")
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// matches any requests those path starts with "/some"
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some.*"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some.*"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches any requests those path does NOT start with "/some"
            .withPath(not("/some.*"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// matches any requests those path does NOT start with "/some"
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "!/some.*"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "!/some.*"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withPathParameters(
                param("cartId", "055CA455-1DF7-45BB-8535-4F83E7266092")
            )
            .withQueryStringParameters(
                param("type", "[A-Z0-9\\-]+")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
    "path": "/some/path/{cartId}",
        "pathParameters": {
            "cartId": ["055CA455-1DF7-45BB-8535-4F83E7266092"]
        },
        "queryStringParameters": {
            "type": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
    "path": "/some/path/{cartId}",
        "pathParameters": {
            "cartId": ["055CA455-1DF7-45BB-8535-4F83E7266092"]
        },
        "queryStringParameters": {
            "type": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path/{cartId}")
            .withPathParameters(
                param("cartId", "[A-Z0-9\\-]+")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path/{cartId}",
        "pathParameters": {
            "cartId": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path/{cartId}",
        "pathParameters": {
            "cartId": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path/{cartId}/{maxItemCount}")
            .withPathParameters(
                schemaParam("cartId", "{\"type\": \"string\", \"pattern\": \"^[A-Z0-9\\-]+$\"}"),
                param(string("maxItemCount"), schemaString("{ \"type\": \"integer\" }"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path/{cartId}/{maxItemCount}",
        "pathParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "pattern": "^[A-Z0-9-]+$"
                }
            }],
            "maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path/{cartId}/{maxItemCount}",
        "pathParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "pattern": "^[A-Z0-9-]+$"
                }
            }],
            "maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

To match a path segment containing multiple values separated by delimiters (e.g. /2024-01-15/report), use a single path parameter with a regex value to match the entire compound segment.

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches paths like /2024-01-15/report or /val1-val2-val3/report
            .withPath("/{compound}/report")
            .withPathParameters(
                param("compound", "[^/]+-[^/]+-[^/]+")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// matches paths like /2024-01-15/report or /val1-val2-val3/report
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/{compound}/report",
        "pathParameters": {
            "compound": ["[^/]+-[^/]+-[^/]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/{compound}/report",
        "pathParameters": {
            "compound": ["[^/]+-[^/]+-[^/]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches any requests that does NOT have a "GET" method
            .withMethod(not("P.*{2,3}"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "P.*{2,3}"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "P.*{2,3}"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches any requests that does NOT have a "GET" method
            .withMethod(not("GET"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// matches any requests that does NOT have a "GET" method
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "!GET"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "!GET"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(
                param("[A-z]{0,10}", "055CA455-1DF7-45BB-8535-4F83E7266092")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "[A-z]{0,10}": ["055CA455-1DF7-45BB-8535-4F83E7266092"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "[A-z]{0,10}": ["055CA455-1DF7-45BB-8535-4F83E7266092"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(
                param("cartId", "[A-Z0-9\\-]+")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "cartId": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "cartId": ["[A-Z0-9\\-]+"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

This example shows the two ways a JSON Schema can be specified to match a query parameter value, either using the schemaParam static builder for parameters or the schemaString for static builder strings.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(
                schemaParam("cartId", "{\"type\": \"string\", \"pattern\": \"^[A-Z0-9\\-]+$\"}"),
                param(string("maxItemCount"), schemaString("{ \"type\": \"integer\" }"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "pattern": "^[A-Z0-9-]+$"
                }
            }],
            "maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "pattern": "^[A-Z0-9-]+$"
                }
            }],
            "maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

This example shows the two ways to specify an optional query parameter value, either using the optionalParam static builder for parameters or the optionalString for static builder strings.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(
                optionalParam("cartId", "[A-Z0-9\\-]+"),
                param(optionalString("maxItemCount"), schemaString("{ \"type\": \"integer\" }")),
                schemaParam(optionalString("userId"), "{ \"type\": \"string\", \"format\": \"uuid\" }")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "?cartId": ["[A-Z0-9\\-]+"],
            "?maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }],
            "?userId": [{
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "queryStringParameters": {
            "?cartId": ["[A-Z0-9\\-]+"],
            "?maxItemCount": [{
                "schema": {
                    "type": "integer"
                }
            }],
            "?userId": [{
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

Matching by keys to multiple-values by SUB_SET is the default mode this ensures at least one value with the same key matches, but MATCHING_KEY is also supported which ensures all values with the same key match.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(new Parameters(
                schemaParam("multiValuedParameter", "{\"type\": \"string\", \"pattern\": \"^[A-Z0-9\\-]+$\"}"),
                param(string("maxItemCount"), schemaString("{ \"type\": \"integer\" }"))
            ).withKeyMatchStyle(KeyMatchStyle.SUB_SET))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );

Matching by SUB_SET is the default mode so nothing needs to be specified for this key match style.

var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path",
        "queryStringParameters" : {
            "multiValuedParameter" : [ {
                "schema" : {
                    "type" : "string",
                    "pattern" : "^[A-Z0-9-]+$"
                }
            } ],
            "maxItemCount" : [ {
                "schema" : {
                    "type" : "integer"
                }
            } ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

Matching by SUB_SET is the default mode so nothing needs to be specified for this key match style.

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path",
        "queryStringParameters" : {
            "multiValuedParameter" : [ {
                "schema" : {
                    "type" : "string",
                    "pattern" : "^[A-Z0-9-]+$"
                }
            } ],
            "maxItemCount" : [ {
                "schema" : {
                    "type" : "integer"
                }
            } ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}'

See REST API for full JSON specification

Matching by keys to multiple-values by SUB_SET is the default mode this ensures at least one value with the same key matches, but MATCHING_KEY is also supported which ensures all values with the same key match.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withQueryStringParameters(new Parameters(
                schemaParam("multiValuedParameter", "{\"type\": \"string\", \"pattern\": \"^[A-Z0-9\\-]+$\"}"),
                param(string("maxItemCount"), schemaString("{ \"type\": \"integer\" }"))
            ).withKeyMatchStyle(KeyMatchStyle.MATCHING_KEY))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path",
        "queryStringParameters" : {
            "keyMatchStyle" : "MATCHING_KEY",
            "multiValuedParameter" : [ {
                "schema" : {
                    "type" : "string",
                    "pattern" : "^[A-Z0-9-]+$"
                }
            } ],
            "maxItemCount" : [ {
                "schema" : {
                    "type" : "integer"
                }
            } ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path",
        "queryStringParameters" : {
            "keyMatchStyle" : "MATCHING_KEY",
            "multiValuedParameter" : [ {
                "schema" : {
                    "type" : "string",
                    "pattern" : "^[A-Z0-9-]+$"
                }
            } ],
            "maxItemCount" : [ {
                "schema" : {
                    "type" : "integer"
                }
            } ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("GET")
            .withPath("/some/path")
            .withHeaders(
                header("Accept", "application/json"),
                header("Accept-Encoding", "gzip, deflate, br")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "GET",
        "path": "/some/path",
        "headers": {
            "Accept": ["application/json"],
            "Accept-Encoding": ["gzip, deflate, br"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "GET",
    "path" : "/some/path",
    "headers" : {
      "Accept" : [ "application/json" ],
      "Accept-Encoding" : [ "gzip, deflate, br" ]
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeader(
                header("Accept.*")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            // matches requests that have any header starting with the name Accept
            "Accept.*": [ "" ]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

// matches requests that have any header starting with the name Accept
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "Accept.*": [ "" ]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeader(
                header("Accept.*", ".*gzip.*")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            // matches requests that have a header with a name starting with Accept and a value containing gzip
            "Accept.*": [".*gzip.*"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

// matches requests that have a header with a name starting with Accept and a value containing gzip
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "Accept.*": [".*gzip.*"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeaders(
                // matches requests that have an Accept header without the value "application/json"
                header(string("Accept"), not("application/json")),
                // matches requests that have an Accept-Encoding without the substring "gzip"
                header(string("Accept-Encoding"), not(".*gzip.*"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            // matches requests that have an Accept header without the value "application/json"
            "Accept": ["!application/json"],
            // matches requests that have an Accept-Encoding without the substring "gzip"
            "Accept-Encoding": ["!.*gzip.*"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path",
    "headers" : {
      "Accept" : [ "!application/json" ],
      "Accept-Encoding" : [ "!.*gzip.*" ]
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeaders(
                // matches requests that do not have either an Accept or an Accept-Encoding header
                header(not("Accept")),
                header(not("Accept-Encoding"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            // matches requests that do not have either an Accept or an Accept-Encoding header
            "!Accept": [".*"],
            "!Accept-Encoding": [".*"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "path" : "/some/path",
    "headers" : {
      "!Accept" : [ ".*" ],
      "!Accept-Encoding" : [ ".*" ]
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeader(
                schemaHeader("Accept.*", "{\"type\": \"string\", \"pattern\": \"^.*gzip.*$\"}")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "Accept.*": [{
                "schema": {
                    "type": "string",
                    "pattern": "^.*gzip.*$"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "Accept.*": [{
                "schema": {
                    "type": "string",
                    "pattern": "^.*gzip.*$"
                }
            }]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

This example shows how to match by either one value (in this case a header) or another value or both.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeaders(
                header("headerOne|headerTwo", ".*"),
                optionalHeader("headerOne", "headerOneValue"),
                optionalHeader("headerTwo", "headerTwoValue")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "headerOne|headerTwo": [".*"],
            "?headerOne": ["headerOneValue"],
            "?headerTwo": ["headerTwoValue"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path",
        "headers": {
            "headerOne|headerTwo": [".*"],
            "?headerOne": ["headerOneValue"],
            "?headerTwo": ["headerTwoValue"]
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

Matching by keys to multiple-values by SUB_SET is the default mode this ensures at least one value with the same key matches, but MATCHING_KEY is also supported which ensures all values with the same key match.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
            .withHeaders(new Headers(
                header("multiValuedHeader", "value.*"),
                header("headerTwo", "headerTwoValue")
            ).withKeyMatchStyle(KeyMatchStyle.MATCHING_KEY))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path",
        "headers" : {
            "keyMatchStyle" : "MATCHING_KEY",
            "multiValuedHeader" : [ "value.*" ],
            "headerTwo" : [ "headerTwoValue" ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path",
        "headers" : {
            "keyMatchStyle" : "MATCHING_KEY",
            "multiValuedHeader" : [ "value.*" ],
            "headerTwo" : [ "headerTwoValue" ]
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("GET")
            .withPath("/view/cart")
            .withCookies(
                cookie("session", "4930456C-C718-476F-971F-CB8E047AB349")
            )
            .withQueryStringParameters(
                param("cartId", "055CA455-1DF7-45BB-8535-4F83E7266092")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "GET",
        "path": "/view/cart",
        "queryStringParameters": {
            "cartId": ["055CA455-1DF7-45BB-8535-4F83E7266092"]
        },
        "cookies": {
            "session": "4930456C-C718-476F-971F-CB8E047AB349"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "GET",
    "path" : "/view/cart",
    "queryStringParameters" : {
      "cartId" : [ "055CA455-1DF7-45BB-8535-4F83E7266092" ]
    },
    "cookies" : {
      "session" : "4930456C-C718-476F-971F-CB8E047AB349"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("GET")
            .withPath("/view/cart")
            .withQueryStringParameters(
                schemaParam("cartId", "{ \"type\": \"string\", \"format\": \"uuid\" }")
            )
            .withCookies(
                schemaCookie("session", "{ \"type\": \"string\", \"format\": \"uuid\" }")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "GET",
        "path": "/view/cart",
        "queryStringParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }]
        },
        "cookies": {
            "session": {
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "GET",
    "path" : "/view/cart",
    "queryStringParameters" : {
      "cartId" : [ "055CA455-1DF7-45BB-8535-4F83E7266092" ]
    },
    "cookies" : {
      "session" : "4930456C-C718-476F-971F-CB8E047AB349"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/view/cart")
            .withCookies(
                optionalCookie("session", schemaString("{ \"type\": \"string\", \"format\": \"uuid\" }"))
            )
            .withQueryStringParameters(
                schemaParam("cartId", "{ \"type\": \"string\", \"format\": \"uuid\" }")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/view/cart",
        "queryStringParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }]
        },
        "cookies": {
            "?session": {
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/view/cart",
        "queryStringParameters": {
            "cartId": [{
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }]
        },
        "cookies": {
            "?session": {
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(subString("some_string"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "STRING",
            "string": "some_string",
            "subString": true
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type": "STRING",
      "string": "some_string",
      "subString": true
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(exact("我说中国话", Charsets.UTF_16))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "STRING",
            "string": "我说中国话",
            "contentType": "text/plain; charset=utf-16"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type" : "STRING",
      "string" : "我说中国话",
      "contentType" : "text/plain; charset=utf-16"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

For details of the full regex syntax supported please see the JDK documentation.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(regex("starts_with_.*"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "REGEX",
            "regex": "starts_with_.*"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest": {
    "body": {
      "type": "REGEX",
      "regex": "starts_with_.*"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("POST")
            .withHeaders(
                header("Content-Type", "application/x-www-form-urlencoded")
            )
            .withBody(
                params(
                    param("email", "joe.blogs@gmail.com"),
                    param("password", "secure_Password123")
                )
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "POST",
        "headers": {
            "Content-Type": ["application/x-www-form-urlencoded"]
        },
        "body": {
            "type": "PARAMETERS",
            "parameters": {
                "email": ["joe.blogs@gmail.com"],
                "password": ["secure_Password123"]
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "method" : "POST",
    "headers" : {
      "Content-Type" : [ "application/x-www-form-urlencoded" ]
    },
    "body" : {
      "type" : "PARAMETERS",
      "parameters" : {
        "email" : [ "joe.blogs@gmail.com" ],
        "password" : [ "secure_Password123" ]
      }
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

Matches if at least one value is returned by the JsonPath expression

For a quick summary the XPath syntax please see w3schools, for details of the full XPath syntax please see www.w3.org

new MockServerClient("localhost", 1080)
    .when(
        request()
            // matches any request with an XML body that contains
            // one or more elements that match the XPath expression
            .withBody(
                xpath("/bookstore/book[price>30]/price")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );

// matches a request with the following body:
/*
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>31.95</price>
  </book>
</bookstore>
 */
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            // matches any request with an XML body that contains
            // one or more elements that match the XPath expression
            "type": "XPATH",
            "xpath": "/bookstore/book[price>30]/price"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
});

// matches a request with the following body:
/*
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>31.95</price>
  </book>
</bookstore>
 */

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type" : "XPATH",
      "xpath" : "/bookstore/book[price>30]/price"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

Matches if at least one value is returned by the JsonPath expression

For a quick summary the XPath syntax please see w3schools, for details of the full XPath syntax please see www.w3.org

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                // matches any request with an XML body that does NOT
                // contain one or more elements that match the XPath expression
                not(xpath("/bookstore/book[price>30]/price"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            // matches any request with an XML body that does NOT
            // contain one or more elements that match the XPath expression
            "not": true,
            "type": "XPATH",
            "xpath": "/bookstore/book[price>30]/price"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "not" : true,
      "type" : "XPATH",
      "xpath" : "/bookstore/book[price>30]/price"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                xml("<bookstore>" + System.lineSeparator() +
                    "   <book nationality=\"ITALIAN\" category=\"COOKING\">" + System.lineSeparator() +
                    "       <title lang=\"en\">Everyday Italian</title>" + System.lineSeparator() +
                    "       <author>Giada De Laurentiis</author>" + System.lineSeparator() +
                    "       <year>2005</year>" + System.lineSeparator() +
                    "       <price>30.00</price>" + System.lineSeparator() +
                    "   </book>" + System.lineSeparator() +
                    "</bookstore>")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "XML",
            "xml":  "<bookstore>\n" +
                    "   <book nationality=\"ITALIAN\" category=\"COOKING\">\n" +
                    "       <title lang=\"en\">Everyday Italian</title>\n" +
                    "       <author>Giada De Laurentiis</author>\n" +
                    "       <year>2005</year>\n" +
                    "       <price>30.00</price>\n" +
                    "   </book>\n" +
                    "</bookstore>"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type" : "XML",
      "xml" : "<bookstore> <book nationality=\"ITALIAN\" category=\"COOKING\"><title lang=\"en\">Everyday Italian</title><author>Giada De Laurentiis</author><year>2005</year><price>30.00</price></book> </bookstore>"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

See XMLUnit documentation for full details of supported placeholders.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                xml("<bookstore>" + System.lineSeparator() +
                    "   <book nationality=\"ITALIAN\" category=\"COOKING\">" + System.lineSeparator() +
                    "       <title lang=\"en\">Everyday Italian</title>" + System.lineSeparator() +
                    "       <author>${xmlunit.ignore}</author>" + System.lineSeparator() +
                    "       <year>${xmlunit.isNumber}</year>" + System.lineSeparator() +
                    "       <price>30.00</price>" + System.lineSeparator() +
                    "   </book>" + System.lineSeparator() +
                    "</bookstore>")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "body" : {
            "type" : "XML",
            "xml" : "<bookstore>\n" +
                "   <book nationality=\"ITALIAN\" category=\"COOKING\">\n" +
                "       <title lang=\"en\">Everyday Italian</title>\n" +
                "       <author>${xmlunit.ignore}</author>\n" +
                "       <year>${xmlunit.isNumber}</year>\n" +
                "       <price>30.00</price>\n" +
                "   </book>\n" +
                "</bookstore>"
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "body" : {
            "type" : "XML",
            "xml" : "<bookstore>\n   <book nationality=\"ITALIAN\" category=\"COOKING\">\n       <title lang=\"en\">Everyday Italian</title>\n       <author>${xmlunit.ignore}</author>\n       <year>${xmlunit.isNumber}</year>\n       <price>30.00</price>\n   </book>\n</bookstore>"
        }
    },
    "httpResponse" : {
        "body" : "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                xmlSchema("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + System.lineSeparator() +
                    "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">" + System.lineSeparator() +
                    "    <!-- XML Schema Generated from XML Document on Wed Jun 28 2017 21:52:45 GMT+0100 (BST) -->" + System.lineSeparator() +
                    "    <!-- with XmlGrid.net Free Online Service http://xmlgrid.net -->" + System.lineSeparator() +
                    "    <xs:element name=\"notes\">" + System.lineSeparator() +
                    "        <xs:complexType>" + System.lineSeparator() +
                    "            <xs:sequence>" + System.lineSeparator() +
                    "                <xs:element name=\"note\" maxOccurs=\"unbounded\">" + System.lineSeparator() +
                    "                    <xs:complexType>" + System.lineSeparator() +
                    "                        <xs:sequence>" + System.lineSeparator() +
                    "                            <xs:element name=\"to\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>" + System.lineSeparator() +
                    "                            <xs:element name=\"from\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>" + System.lineSeparator() +
                    "                            <xs:element name=\"heading\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>" + System.lineSeparator() +
                    "                            <xs:element name=\"body\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>" + System.lineSeparator() +
                    "                        </xs:sequence>" + System.lineSeparator() +
                    "                    </xs:complexType>" + System.lineSeparator() +
                    "                </xs:element>" + System.lineSeparator() +
                    "            </xs:sequence>" + System.lineSeparator() +
                    "        </xs:complexType>" + System.lineSeparator() +
                    "    </xs:element>" + System.lineSeparator() +
                    "</xs:schema>")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "XML_SCHEMA",
            "xmlSchema": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n" +
            "    <!-- XML Schema Generated from XML Document on Wed Jun 28 2017 21:52:45 GMT+0100 (BST) -->\n" +
            "    <!-- with XmlGrid.net Free Online Service http://xmlgrid.net -->\n" +
            "    <xs:element name=\"notes\">\n" +
            "        <xs:complexType>\n" +
            "            <xs:sequence>\n" +
            "                <xs:element name=\"note\" maxOccurs=\"unbounded\">\n" +
            "                    <xs:complexType>\n" +
            "                        <xs:sequence>\n" +
            "                            <xs:element name=\"to\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>\n" +
            "                            <xs:element name=\"from\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>\n" +
            "                            <xs:element name=\"heading\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>\n" +
            "                            <xs:element name=\"body\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element>\n" +
            "                        </xs:sequence>\n" +
            "                    </xs:complexType>\n" +
            "                </xs:element>\n" +
            "            </xs:sequence>\n" +
            "        </xs:complexType>\n" +
            "    </xs:element>\n</xs:schema>"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type" : "XML_SCHEMA",
      "xmlSchema" : "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\"> <xs:element name=\"notes\"> <xs:complexType> <xs:sequence> <xs:element name=\"note\" maxOccurs=\"unbounded\"> <xs:complexType> <xs:sequence> <xs:element name=\"to\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element> <xs:element name=\"from\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element> <xs:element name=\"heading\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element> <xs:element name=\"body\" minOccurs=\"1\" maxOccurs=\"1\" type=\"xs:string\"></xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                xmlSchemaFromResource("org/mockserver/examples/mockserver/testXmlSchema.xsd")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );

JSON body matcher supports two mode STRICT which matches all fields, order of arrays and no additional fields allowed, and ONLY_MATCHING_FIELDS which only matches fields provided in the request matcher.

When matching JSON arrays the number of elements in the array must always match, however if ONLY_MATCHING_FIELDS mode is specified only the fields in the each array element in the matcher will be matched against each corresponding object in the array.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                json("{" + System.lineSeparator() +
                        "    \"id\": 1," + System.lineSeparator() +
                        "    \"name\": \"A green door\"," + System.lineSeparator() +
                        "    \"price\": 12.50," + System.lineSeparator() +
                        "    \"tags\": [\"home\", \"green\"]" + System.lineSeparator() +
                        "}",
                    MatchType.STRICT
                )
            )
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "JSON",
            "json": {
                "id": 1,
                "name": "A green door",
                "price": 12.50,
                "tags": ["home", "green"]
            },
            "matchType": "STRICT"
        }
    },
    "httpResponse": {
        "statusCode": 202,
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "body": {
            "type": "JSON",
            "json": {
                "id": 1,
                "name": "A green door",
                "price": 12.50,
                "tags": ["home", "green"]
            },
            "matchType": "STRICT"
        }
    },
    "httpResponse": {
        "statusCode": 202,
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

JSON body matcher supports two mode STRICT which matches all fields, order of arrays and no additional fields allowed, and ONLY_MATCHING_FIELDS which only matches fields provided in the request matcher.

When matching JSON arrays the number of elements in the array must always match, however if ONLY_MATCHING_FIELDS mode is specified only the fields in the each array element in the matcher will be matched against each corresponding object in the array.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                json("{" + System.lineSeparator() +
                        "    \"id\": 1," + System.lineSeparator() +
                        "    \"name\": \"A green door\"," + System.lineSeparator() +
                        "    \"price\": 12.50," + System.lineSeparator() +
                        "    \"tags\": [\"home\", \"green\"]" + System.lineSeparator() +
                        "}",
                    MatchType.ONLY_MATCHING_FIELDS
                )
            )
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "id": 1,
            "name": "A green door",
            "price": 12.50,
            "tags": ["home", "green"]
        }
    },
    "httpResponse": {
        "statusCode": 202,
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "body": {
            "id": 1,
            "name": "A green door",
            "price": 12.50,
            "tags": ["home", "green"]
        }
    },
    "httpResponse": {
        "statusCode": 202,
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

JSON body matcher supports two mode STRICT which matches all fields, order of arrays and no additional fields allowed, and ONLY_MATCHING_FIELDS which only matches fields provided in the request matcher.

When matching JSON arrays the number of elements in the array must always match, however if ONLY_MATCHING_FIELDS mode is specified only the fields in the each array element in the matcher will be matched against each corresponding object in the array.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                json(
                    "{\"context\": [{\"source\": \"DECISION_REQUEST\"},{\"source\": \"DECISION_REQUEST\"},{\"source\": \"DECISION_REQUEST\"}]}",
                    MatchType.ONLY_MATCHING_FIELDS
                )
            )
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "POST",
        "path": "/json",
        "body": {
            "type": "JSON",
            "json": {
                "context": [
                    {
                        "source": "DECISION_REQUEST"
                    },
                    {
                        "source": "DECISION_REQUEST"
                    },
                    {
                        "source": "DECISION_REQUEST"
                    }
                ]
            },
            "matchType": "ONLY_MATCHING_FIELDS"
        }
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "some response"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "method": "POST",
        "path": "/json",
        "body": {
            "type": "JSON",
            "json": {
                "context": [
                    {
                        "source": "DECISION_REQUEST"
                    },
                    {
                        "source": "DECISION_REQUEST"
                    },
                    {
                        "source": "DECISION_REQUEST"
                    }
                ]
            },
            "matchType": "ONLY_MATCHING_FIELDS"
        }
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "some response"
    }
}'

See REST API for full JSON specification

See JSONUnit documentation for full details of supported placeholders.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                json("{" + System.lineSeparator() +
                        "    \"id\": 1," + System.lineSeparator() +
                        "    \"name\": \"A green door\"," + System.lineSeparator() +
                        "    \"price\": \"${json-unit.ignore-element}\"," + System.lineSeparator() +
                        "    \"enabled\": \"${json-unit.any-boolean}\"," + System.lineSeparator() +
                        "    \"tags\": [\"home\", \"green\"]" + System.lineSeparator() +
                        "}",
                    MatchType.ONLY_MATCHING_FIELDS
                )
            )
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "body" : {
            "type" : "JSON",
            "json" : {
                "id" : 1,
                "name" : "A green door",
                "price" : "${json-unit.ignore-element}",
                "enabled" : "${json-unit.any-boolean}",
                "tags" : [ "home", "green" ]
            }
        }
    },
    "httpResponse" : {
        "statusCode" : 202,
        "body" : "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "body" : {
            "type" : "JSON",
            "json" : {
                "id" : 1,
                "name" : "A green door",
                "price" : "${json-unit.ignore-element}",
                "enabled" : "${json-unit.any-boolean}",
                "tags" : [ "home", "green" ]
            }
        }
    },
    "httpResponse" : {
        "statusCode" : 202,
        "body" : "some_response_body"
    }
}'

See REST API for full JSON specification

By default, JSON body matching treats 1 and 1.0 as different values because they have different numeric types (integer vs double). When matchNumbersAsStrings is set to true, numbers are compared by numeric value so 1, 1.0 and 1.00 are all considered equal. This is useful when different languages or serializers produce different numeric representations for the same value.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                json("{" + System.lineSeparator() +
                        "    \"id\": 1," + System.lineSeparator() +
                        "    \"price\": 12.5" + System.lineSeparator() +
                        "}",
                    MatchType.ONLY_MATCHING_FIELDS,
                    true // matchNumbersAsStrings
                )
            )
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
            .withBody("some_response_body")
    );

This expectation will match requests containing {"id": 1.0, "price": 12.50} as well as {"id": 1, "price": 12.5}.

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "body": {
            "type": "JSON",
            "json": {
                "id": 1,
                "price": 12.5
            },
            "matchNumbersAsStrings": true
        }
    },
    "httpResponse": {
        "statusCode": 202,
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

For details of the full json schema supported please see json-schema.org.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                jsonSchema("{" + System.lineSeparator() +
                    "    \"$schema\": \"https://json-schema.org/draft-04/schema#\"," + System.lineSeparator() +
                    "    \"title\": \"Product\"," + System.lineSeparator() +
                    "    \"description\": \"A product from Acme catalog\"," + System.lineSeparator() +
                    "    \"type\": \"object\"," + System.lineSeparator() +
                    "    \"properties\": {" + System.lineSeparator() +
                    "        \"id\": {" + System.lineSeparator() +
                    "            \"description\": \"The unique identifier for a product\"," + System.lineSeparator() +
                    "            \"type\": \"integer\"" + System.lineSeparator() +
                    "        }," + System.lineSeparator() +
                    "        \"name\": {" + System.lineSeparator() +
                    "            \"description\": \"Name of the product\"," + System.lineSeparator() +
                    "            \"type\": \"string\"" + System.lineSeparator() +
                    "        }," + System.lineSeparator() +
                    "        \"price\": {" + System.lineSeparator() +
                    "            \"type\": \"number\"," + System.lineSeparator() +
                    "            \"minimum\": 0," + System.lineSeparator() +
                    "            \"exclusiveMinimum\": true" + System.lineSeparator() +
                    "        }," + System.lineSeparator() +
                    "        \"tags\": {" + System.lineSeparator() +
                    "            \"type\": \"array\"," + System.lineSeparator() +
                    "            \"items\": {" + System.lineSeparator() +
                    "                \"type\": \"string\"" + System.lineSeparator() +
                    "            }," + System.lineSeparator() +
                    "            \"minItems\": 1," + System.lineSeparator() +
                    "            \"uniqueItems\": true" + System.lineSeparator() +
                    "        }" + System.lineSeparator() +
                    "    }," + System.lineSeparator() +
                    "    \"required\": [\"id\", \"name\", \"price\"]" + System.lineSeparator() +
                    "}"))
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            "type": "JSON_SCHEMA",
            "jsonSchema": {
                "$schema": "https://json-schema.org/draft-04/schema#",
                "title": "Product",
                "description": "A product from Acme catalog",
                "type": "object",
                "properties": {
                    "id": {
                        "description": "The unique identifier for a product",
                        "type": "integer"
                    },
                    "name": {
                        "description": "Name of the product",
                        "type": "string"
                    },
                    "price": {
                        "type": "number",
                        "minimum": 0,
                        "exclusiveMinimum": true
                    },
                    "tags": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1,
                        "uniqueItems": true
                    }
                },
                "required": [
                    "id",
                    "name",
                    "price"
                ]
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "body": {
            "type": "JSON_SCHEMA",
            "jsonSchema": {
                "$schema": "https://json-schema.org/draft-04/schema#",
                "title": "Product",
                "description": "A product from Acme catalog",
                "type": "object",
                "properties": {
                    "id": {
                        "description": "The unique identifier for a product",
                        "type": "integer"
                    },
                    "name": {
                        "description": "Name of the product",
                        "type": "string"
                    },
                    "price": {
                        "type": "number",
                        "minimum": 0,
                        "exclusiveMinimum": true
                    },
                    "tags": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1,
                        "uniqueItems": true
                    }
                },
                "required": [
                    "id",
                    "name",
                    "price"
                ]
            }
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

Matches if at least one value is returned by the JsonPath expression. For details of the full JsonPath supported please see github.com/json-path/JsonPath.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                // matches any request with an JSON body that contain
                // one or more fields that match the JsonPath expression
                jsonPath("$.store.book[?(@.price < 10)]")
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            // matches any request with an JSON body that contain
            // one or more fields that match the JsonPath expression
            "type": "JSON_PATH",
            "jsonPath": "$.store.book[?(@.price < 10)]"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "type": "JSON_PATH",
      "jsonPath": "$.store.book[?(@.price < 10)]"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

Matches if at least one value is returned by the JsonPath expression. For details of the full JsonPath supported please see github.com/json-path/JsonPath.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withBody(
                // matches any request with an JSON body that does NOT contain
                // one or more fields that match the JsonPath expression
                not(jsonPath("$.store.book[?(@.price < 10)]"))
            )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "body": {
            // matches any request with an JSON body that does NOT contain
            // one or more fields that match the JsonPath expression
            "not": true,
            "type": "JSON_PATH",
            "jsonPath": "$.store.book[?(@.price < 10)]"
        }
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "httpRequest" : {
    "body" : {
      "not": true,
      "type": "JSON_PATH",
      "jsonPath": "$.store.book[?(@.price < 10)]"
    }
  },
  "httpResponse" : {
    "body" : "some_response_body"
  }
}'

See REST API for full JSON specification

byte[] pngBytes = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("org/mockserver/examples/mockserver/test.png"));
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("POST")
            .withHeaders(
                header("content-type", "image/png"),
                header("content-disposition", "form-data; name=\"test.png\"; filename=\"test.png\"")
            )
            .withBody(binary(pngBytes))
    )
    .respond(
        response()
            .withBody("png_saved_response")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "POST"
        "headers": {
            "content-type": ["image/png"],
            "content-disposition": ["form-data; name=\"test.png\"; filename=\"test.png\""]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "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"
        }
    },
    "httpResponse" : {
        "body" : "png_saved_response"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "method": "POST"
        "headers": {
            "content-type": ["image/png"],
            "content-disposition": ["form-data; name=\"test.png\"; filename=\"test.png\""]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "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"
        }
    },
    "httpResponse" : {
        "body" : "png_saved_response"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .upsert(
        new Expectation(
            request().withPath("/some/path"),
            Times.once(),
            TimeToLive.exactly(TimeUnit.SECONDS, 60L),
            100
        )
        .withId("some_unique_id")
        .thenRespond(response().withBody("some_response_body"))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "id": "some_unique_id",
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    },
    "timeToLive": {
        "timeUnit": "SECONDS",
        "timeToLive": 60,
        "unlimited": false
    },
    "priority" : 100
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
  "id": "some_unique_id",
  "httpRequest" : {
    "path" : "/some/path"
  },
  "httpResponse" : {
    "body" : "some_response_body"
  },
  "times" : {
    "remainingTimes" : 1,
    "unlimited" : false
  },
  "timeToLive" : {
    "timeUnit" : "SECONDS",
    "timeToLive" : 60,
    "unlimited" : false
  },
  "priority" : 100
}'

See REST API for full JSON specification

 

An open api request matcher can contain any of the following fields:

MockServer creates a set of request properties matchers for each open api request matcher, to ensures control-plane logic such as clearing expectations or retrieving expectations work consistently between the two types of request matchers, this can be viewed in the MockServer UI active expectations section.

The following code examples show how to match request using an Open API specification. For more examples see the code examples folder in the git repository.

For brevity static imports have not been included in the Java code examples so please add the following static imports if copying this code

import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

new MockServerClient("localhost", 1080)
    .when(
        openAPI(
            "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json"
        )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        openAPI(
            "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
            "showPetById"
        )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        openAPI(
            "file:/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json"
        )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "specUrlOrPayload": "file:/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "specUrlOrPayload": "file:/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        openAPI(
            "org/mockserver/openapi/openapi_petstore_example.json"
        )
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "specUrlOrPayload": "org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "specUrlOrPayload": "org/mockserver/openapi/openapi_petstore_example.json"
    },
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        new OpenAPIDefinition()
            .withSpecUrlOrPayload(
                FileReader.readFileFromClassPathOrPath("/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json")
            )
            .withOperationId("listPets")
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var fs = require('fs');
try {
    var mockServerClient = require('mockserver-client').mockServerClient;
    mockServerClient("localhost", 1080).mockAnyResponse({
        "httpRequest": {
            "specUrlOrPayload": fs.readFileSync("/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json", "utf8"),
            "operationId": "showPetById"
        },
        "httpResponse": {
            "body": "some_response_body"
        }
    }).then(
        function () {
            console.log("expectation created");
        },
        function (error) {
            console.log(error);
        }
    );
} catch(e) {
    console.log('Error:', e.stack);
}

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d "{
    \"httpRequest\": {
        \"specUrlOrPayload\": `cat /Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json`
    },
    \"httpResponse\": {
        \"body\": \"some_response_body\"
    }
}"
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
      "specUrlOrPayload" : {
        "openapi" : "3.0.0",
        "info" : {
          "version" : "1.0.0",
          "title" : "Swagger Petstore",
          "license" : {
            "name" : "MIT"
          }
        },
        "servers" : [ {
          "url" : "http://petstore.swagger.io/v1"
        } ],
        "paths" : {
          "/pets" : {
            "get" : {
              "summary" : "List all pets",
              "operationId" : "listPets",
              "tags" : [ "pets" ],
              "parameters" : [ {
                "name" : "limit",
                "in" : "query",
                "description" : "How many items to return at one time (max 100)",
                "required" : false,
                "schema" : {
                  "type" : "integer",
                  "format" : "int32"
                }
              } ],
              "responses" : {
                "200" : {
                  "description" : "A paged array of pets",
                  "headers" : {
                    "x-next" : {
                      "description" : "A link to the next page of responses",
                      "schema" : {
                        "type" : "string"
                      }
                    }
                  },
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Pets"
                      }
                    }
                  }
                },
                "500" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                },
                "default" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                }
              }
            },
            "post" : {
              "summary" : "Create a pet",
              "operationId" : "createPets",
              "tags" : [ "pets" ],
              "requestBody" : {
                "description" : "a pet",
                "required" : true,
                "content" : {
                  "application/json" : {
                    "schema" : {
                      "$ref" : "#/components/schemas/Pet"
                    }
                  },
                  "*/*" : {
                    "schema" : {
                      "$ref" : "#/components/schemas/Pet"
                    }
                  }
                }
              },
              "responses" : {
                "201" : {
                  "description" : "Null response"
                },
                "400" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                },
                "500" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                },
                "default" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                }
              }
            }
          },
          "/pets/{petId}" : {
            "get" : {
              "summary" : "Info for a specific pet",
              "operationId" : "showPetById",
              "tags" : [ "pets" ],
              "parameters" : [ {
                "name" : "petId",
                "in" : "path",
                "required" : true,
                "description" : "The id of the pet to retrieve",
                "schema" : {
                  "type" : "string"
                }
              }, {
                "in" : "header",
                "name" : "X-Request-ID",
                "schema" : {
                  "type" : "string",
                  "format" : "uuid"
                },
                "required" : true
              } ],
              "responses" : {
                "200" : {
                  "description" : "Expected response to a valid request",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Pet"
                      }
                    }
                  }
                },
                "400" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                },
                "500" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                },
                "default" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                }
              }
            }
          },
          "/some/path" : {
            "get" : {
              "summary" : "Additional request with extra matchers",
              "operationId" : "somePath",
              "tags" : [ "pets" ],
              "parameters" : [ {
                "name" : "limit",
                "in" : "query",
                "description" : "How many items to return at one time (max 100)",
                "required" : false,
                "schema" : {
                  "type" : "integer",
                  "format" : "int32"
                }
              }, {
                "in" : "header",
                "name" : "X-Request-ID",
                "schema" : {
                  "type" : "string",
                  "format" : "uuid"
                },
                "required" : true
              } ],
              "responses" : {
                "200" : {
                  "description" : "Expected response to a valid request",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Pet"
                      }
                    }
                  }
                },
                "default" : {
                  "description" : "unexpected error",
                  "content" : {
                    "application/json" : {
                      "schema" : {
                        "$ref" : "#/components/schemas/Error"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "components" : {
          "schemas" : {
            "Pet" : {
              "type" : "object",
              "required" : [ "id", "name" ],
              "properties" : {
                "id" : {
                  "type" : "integer",
                  "format" : "int64"
                },
                "name" : {
                  "type" : "string"
                },
                "tag" : {
                  "type" : "string"
                }
              }
            },
            "Pets" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/components/schemas/Pet"
              }
            },
            "Error" : {
              "type" : "object",
              "required" : [ "code", "message" ],
              "properties" : {
                "code" : {
                  "type" : "integer",
                  "format" : "int32"
                },
                "message" : {
                  "type" : "string"
                }
              }
            }
          }
        }
      },
      "operationId" : "listPets"
    },
    "httpResponse" : {
      "body" : "some_response_body"
    }
  }'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        new OpenAPIDefinition()
            .withSpecUrlOrPayload(
                "\nopenapi: 3.0.0\ninfo:\n  version: 1.0.0\n  title: Swagger Petstore\n  license:\n    name: MIT\nservers:\n  - url: http://petstore.swagger.io/v1\npaths:\n  /pets:\n    get:\n      summary: List all pets\n      operationId: listPets\n      tags:\n        - pets\n      parameters:\n        - name: limit\n          in: query\n          description: How many items to return at one time (max 100)\n          required: false\n          schema:\n            type: integer\n            format: int32\n      responses:\n        '200':\n          description: A paged array of pets\n          headers:\n            x-next:\n              description: A link to the next page of responses\n              schema:\n                type: string\n              examples:\n                two:\n                  value: \"/pets?query=752cd724e0d7&page=2\"\n                end:\n                  value: \"\"\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Pets'\n        '500':\n          description: unexpected error\n          headers:\n            x-code:\n              description: The error code\n              schema:\n                type: integer\n                format: int32\n                example: 90\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n    post:\n      summary: Create a pet\n      operationId: createPets\n      tags:\n        - pets\n      requestBody:\n        description: a pet\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Pet'\n          '*/*':\n            schema:\n              $ref: '#/components/schemas/Pet'\n      responses:\n        '201':\n          description: Null response\n        '400':\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n        '500':\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n  /pets/{petId}:\n    get:\n      summary: Info for a specific pet\n      operationId: showPetById\n      tags:\n        - pets\n      parameters:\n        - name: petId\n          in: path\n          required: true\n          description: The id of the pet to retrieve\n          schema:\n            type: string\n        - in: header\n          name: X-Request-ID\n          schema:\n            type: string\n            format: uuid\n          required: true\n      responses:\n        '200':\n          description: Expected response to a valid request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Pet'\n              examples:\n                Crumble:\n                  value:\n                    id: 2\n                    name: Crumble\n                    tag: dog\n                Boots:\n                  value:\n                    id: 3\n                    name: Boots\n                    tag: cat\n        '500':\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      required:\n        - id\n        - name\n      properties:\n        id:\n          type: integer\n          format: int64\n        name:\n          type: string\n        tag:\n          type: string\n      example:\n        id: 1\n        name: Scruffles\n        tag: dog\n    Pets:\n      type: array\n      items:\n        $ref: '#/components/schemas/Pet'\n    Error:\n      type: object\n      required:\n        - code\n        - message\n      properties:\n        code:\n          type: integer\n          format: int32\n        message:\n          type: string\n",
      "operationId" : "listPets"
    },
    "times" : {
      "unlimited" : true
    },
    "timeToLive" : {
      "unlimited" : true
    },
    "httpResponse" : {
      "body" : "some_response_body"
    }
  }'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        new OpenAPIDefinition()
            .withSpecUrlOrPayload(
               FileReader.readFileFromClassPathOrPath("/Users/jamesbloom/git/mockserver/mockserver/mockserver-core/target/test-classes/org/mockserver/openapi/openapi_petstore_example.json")
            )
            .withOperationId("listPets"),
        Times.exactly(2)
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest":{
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse":{
        "statusCode": 200,
        "body": "some_body"
    },
    "times": {
        "remainingTimes": 2
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest":{
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse":{
        "statusCode": 200,
        "body": "some_body"
    },
    "times": {
        "remainingTimes": 2
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .upsert(
        new Expectation(
            openAPI(
               "org/mockserver/openapi/openapi_petstore_example.json",
               "showPetById"
            ),
            Times.once(),
            TimeToLive.exactly(TimeUnit.SECONDS, 60L),
            100
        )
        .withId("630a6e5b-9d61-4668-a18f-a0d3df558583")
        .thenRespond(response().withBody("some_response_body"))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "id": "630a6e5b-9d61-4668-a18f-a0d3df558583",
    "priority": 0,
    "httpRequest":{
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse":{
        "statusCode": 200,
        "body": "some_response_body"
    },
    "times":{
        "unlimited": true
    },
    "timeToLive":{
        "unlimited": true
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "id": "630a6e5b-9d61-4668-a18f-a0d3df558583",
    "priority": 0,
    "httpRequest":{
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "httpResponse":{
        "statusCode": 200,
        "body": "some_response_body"
    },
    "times":{
        "unlimited": true
    },
    "timeToLive":{
        "unlimited": true
    }
}'

See REST API for full JSON specification

 

Actions

Actions can be one of the following types:

If no action is present for a request because no request matcher was matched then:

  • if MockServer is being used as a proxy the request is proxied to its destination un-modified
  • if the request host header does not match the hostname or IP the request automatically proxied to the host header
 

A response action can be:

The following code examples show how to create different response actions.

new MockServerClient("localhost", 1080)
    // this request matcher matches every request
    .when(
        request()
    )
    .respond(
        response()
            .withBody("some_response_body")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    // if no request matcher is specified then every request matched
    "httpResponse": {
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

# if no request matcher is specified then every request matched
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpResponse": {
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

FileBody loads the response content from a file at response time, rather than embedding the content directly in the expectation. This is useful when the response payload is large (e.g. sample JSON or XML files), generated externally, or shared across multiple expectations. The file path can be absolute or relative to the working directory.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/api/data")
    )
    .respond(
        response()
            .withBodyFromFile("/path/to/response.json")
    );

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/api/data")
    )
    .respond(
        response()
            .withBodyFromFile("/path/to/response.json", MediaType.APPLICATION_JSON)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/api/data"
    },
    "httpResponse": {
        "body": {
            "type": "FILE",
            "filePath": "/path/to/response.json",
            "contentType": "application/json"
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/api/data"
    },
    "httpResponse": {
        "body": {
            "type": "FILE",
            "filePath": "/path/to/response.json",
            "contentType": "application/json"
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    // this request matcher matches every request
    .when(
        request()
    )
    .respond(
        response()
            .withHeader(
                CONTENT_TYPE.toString(),
                MediaType.create("text", "plain").withCharset(Charsets.UTF_16).toString()
            )
            .withBody("我说中国话".getBytes(Charsets.UTF_16))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    // if no request matcher is specified then every request matched
    "httpResponse": {
        "headers": {
            "content-type": ["text/plain; charset=utf-16"]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "/v9iEYv0Ti1W/Yvd"
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

# if no request matcher is specified then every request matched
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpResponse": {
        "headers": {
            "content-type": ["text/plain; charset=utf-16"]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "/v9iEYv0Ti1W/Yvd"
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("GET")
            .withPath("/farsi_body")
    )
    .respond(
        response()
            .withBody(json("سلام", MediaType.APPLICATION_JSON_UTF_8))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "GET",
        "path": "/simple"
    },
    "httpResponse": {
        "body": {
            "type": "STRING",
            "string": "سلام",
            "contentType": "text/plain; charset=utf-8"
         }
    },
    "times": {
        "unlimited": true
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT http://localhost:1080/mockserver/expectation -H "Content-Type: application/json; charset=utf-8" --data '{
    "httpRequest": {
        "method": "GET",
        "path": "/simple"
    },
    "httpResponse": {
        "body": {
            "type": "STRING",
            "string": "سلام",
            "contentType": "text/plain; charset=utf-8"
         }
    },
    "times": {
        "unlimited": true
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    // this request matcher matches every request
    .when(
        request()
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withHeader("Content-Type", "plain/text")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    // if no request matcher is specified then every request matched
    "httpResponse": {
        "headers": {
            "Content-Type": ["plain/text"]
        },
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT http://localhost:1080/mockserver/expectation -H "Content-Type: application/json; charset=utf-8" --data '{
    "httpResponse": {
        "headers": {
            "Content-Type": ["plain/text"]
        },
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    // this request matcher matches every request
    .when(
        request()
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withHeader("Content-Type", "plain/text")
            .withCookie("Session", "97d43b1e-fe03-4855-926a-f448eddac32f")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    // if no request matcher is specified then every request matched
    "httpResponse": {
        "headers": {
            "Content-Type": ["plain/text"]
        },
        "cookies": {
            "Session": "97d43b1e-fe03-4855-926a-f448eddac32f"
        },
        "body": "some_response_body"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT http://localhost:1080/mockserver/expectation -H "Content-Type: application/json; charset=utf-8" --data '{
    "httpResponse": {
        "headers": {
            "Content-Type": ["plain/text"]
        },
        "cookies": {
            "Session": "97d43b1e-fe03-4855-926a-f448eddac32f"
        },
        "body": "some_response_body"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("POST")
            .withPath("/some/path")
    )
    .respond(
        response()
            .withStatusCode(418)
            .withReasonPhrase("I'm a teapot")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "method": "POST",
        "path": "/some/path"
    },
    "httpResponse": {
        "statusCode": 418,
        "reasonPhrase": "I'm a teapot"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "method": "POST",
        "path": "/some/path"
    },
    "httpResponse": {
        "statusCode": 418,
        "reasonPhrase": "I'm a teapot"
    }
}'

See REST API for full JSON specification

byte[] pngBytes = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("org/mockserver/examples/mockserver/test.png"));
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/ws/rest/user/[0-9]+/icon/[0-9]+\\.png")
    )
    .respond(
        response()
            .withStatusCode(HttpStatusCode.OK_200.code())
            .withHeaders(
                header(CONTENT_TYPE.toString(), MediaType.PNG.toString()),
                header(CONTENT_DISPOSITION.toString(), "form-data; name=\"test.png\"; filename=\"test.png\"")
            )
            .withBody(binary(pngBytes))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/ws/rest/user/[0-9]+/icon/[0-9]+\\.png"
    },
    "httpResponse": {
        "statusCode": 200,
        "headers": {
            "content-type": ["image/png"],
            "content-disposition": ["form-data; name=\"test.png\"; filename=\"test.png\""]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "iVBORw0KGgoAAAANSUhEUgAAAqwAAAApCAIAAAB/QuwlAAAK+GlDQ1BJQ0MgUHJvZmlsZQAASA2tl3dcU8kWx+fe9EYLICAl9CZIr9JrAAXpYCMkgYQSYgoCVpTFFVwLKiKgrugiiIJrAWQtiAULoljAvkEWFXVdLIiKypvAEvfzPm//e5PP3Pne35w598zcmXzOBYBGZQmFWagKANkCiSg6xJ+RmJTMIDwGWKAF8EAf2LHYYqFfVFQE+NfyoRcg8s5bNnJf/2r2vztUOVwxGwAkCnancsTsbMjHYH3PFookAGDqoG68RCKUcxdkdREMELJMzumT/F7OqROMJU7YxEYHAIDVBYBIZbFE6QBQLaDOyGWnQz/UUMh2Ag5fADkPsjebx+JAboU8Izs7R85/QLZI/Yef9H8wi5Wq8MlipSt4ci5wJHxwIF8szGLlT9z8Py/ZWVK4XhPFEF6pPFFoNGwT4ZpVZ+aEK1iQOidySufDGU0xTxoaN8VscQBcy8mxHFZg+BRLM+P8ppglgvS3DV/CjJ1iUU60wr8ga458f0zEwOMyFcwVB8VM6Wn8YOYUF/BiE6Y4lx8/Z4rFmTGKGAp4AQpdJI1WxJwmClbMMVsMR/79XDbr+7MkvFj5O56Ih8MNDJpiriBOEY9Q4q/wI8ya2N8T9tysEIUuzo1RjJWIYhV6BitMvl8n7IWSKMWagEDAB2IgBFmABfIBAyyB9xLAg5QGcoAIsAEXcOBdNAgB/rDNhioHagxgAYLgaCasDKjlQk0Ef/yJXksJNw/uWwACcoT5In46T8LwgyeNy2AK2LYzGA529k4wGHhu5TYAvLs7cR4RTeJ3bYcDAEFVcI9wvmtujwA4CM+AWu93zaQTANooAKffsaWi3El/WHmDA2SgDNSBNvxPMIbR2gAH4AI8gS+MOwxEgliQBBbC+fHgnERw3stAISgGpWAT2AYqwW6wF9SBQ+AIaAEnwVlwEVwFN8Ad8ADIwCB4CYbBBzCGIAgBoSF0RBsxQEwRa8QBcUO8kSAkAolGkpAUJB0RIFJkGbIGKUXKkEpkD1KP/IqcQM4il5Ee5B7Sjwwhb5HPKAalouqoHmqGzkTdUD80HI1FF6Dp6GK0AC1CN6AVaA16EG1Gz6JX0TuoDH2JjmAAhoLRxBhibDBumABMJCYZk4YRYVZgSjDlmBpMI6YN04m5hZFhXmE+YfFYOpaBtcF6YkOxcVg2djF2BXY9thJbh23GnsfewvZjh7HfcDScLs4a54Fj4hJx6bgluGJcOa4Wdxx3AXcHN4j7gMfjNfHmeFd8KD4Jn4Ffil+P34lvwrfje/AD+BECgaBNsCZ4ESIJLIKEUEzYQThIOEO4SRgkfCRSiAZEB2IwMZkoIK4mlhMPEE8TbxKfEcdIKiRTkgcpksQh5ZM2kvaR2kjXSYOkMbIq2ZzsRY4lZ5ALyRXkRvIF8kPyOwqFYkRxp8yl8CmrKBWUw5RLlH7KJ6oa1YoaQJ1PlVI3UPdT26n3qO9oNJoZzZeWTJPQNtDqaedoj2kflehKtkpMJY7SSqUqpWalm0qvlUnKpsp+yguVC5TLlY8qX1d+pUJSMVMJUGGprFCpUjmh0qcyokpXtVeNVM1WXa96QPWy6nM1gpqZWpAaR61Iba/aObUBOoZuTA+gs+lr6PvoF+iD6nh1c3WmeoZ6qfoh9W71YQ01DSeNeI08jSqNUxoyTYymmSZTM0tzo+YRzV7Nz9P0pvlN405bN61x2s1po1rTtXy1uFolWk1ad7Q+azO0g7QztTdrt2g/0sHqWOnM1Vmis0vngs6r6erTPaezp5dMPzL9vi6qa6UbrbtUd69ul+6Inr5eiJ5Qb4feOb1X+pr6vvoZ+lv1T+sPGdANvA34BlsNzhi8YGgw/BhZjArGecawoa5hqKHUcI9ht+GYkblRnNFqoyajR8ZkYzfjNOOtxh3GwyYGJrNNlpk0mNw3JZm6mfJMt5t2mo6amZslmK01azF7bq5lzjQvMG8wf2hBs/CxWGxRY3HbEm/pZplpudPyhhVq5WzFs6qyum6NWrtY8613WvfMwM1wnyGYUTOjz4Zq42eTa9Ng02+raRthu9q2xfb1TJOZyTM3z+yc+c3O2S7Lbp/dA3s1+zD71fZt9m8drBzYDlUOtx1pjsGOKx1bHd84WTtxnXY53XWmO892Xuvc4fzVxdVF5NLoMuRq4priWu3a56buFuW23u2SO87d332l+0n3Tx4uHhKPIx5/edp4Znoe8Hw+y3wWd9a+WQNeRl4srz1eMm+Gd4r3z94yH0Mflk+NzxNfY1+Ob63vMz9Lvwy/g36v/e38Rf7H/UcDPAKWB7QHYgJDAksCu4PUguKCKoMeBxsFpwc3BA+HOIcsDWkPxYWGh24O7WPqMdnMeuZwmGvY8rDz4dTwmPDK8CcRVhGiiLbZ6Oyw2VtmP5xjOkcwpyUSRDIjt0Q+ijKPWhz121z83Ki5VXOfRttHL4vujKHHLIo5EPMh1j92Y+yDOIs4aVxHvHL8/Pj6+NGEwISyBFnizMTliVeTdJL4Sa3JhOT45NrkkXlB87bNG5zvPL94fu8C8wV5Cy4v1FmYtfDUIuVFrEVHU3ApCSkHUr6wIlk1rJFUZmp16jA7gL2d/ZLjy9nKGeJ6ccu4z9K80srSnqd7pW9JH+L58Mp5r/gB/Er+m4zQjN0Zo5mRmfszx7MSspqyidkp2ScEaoJMwfkc/Zy8nB6htbBYKFvssXjb4mFRuKhWjIgXiFsl6jBB6pJaSH+Q9ud651blflwSv+RonmqeIK8r3yp/Xf6zguCCX5Zil7KXdiwzXFa4rH+53/I9K5AVqSs6VhqvLFo5uCpkVV0huTCz8Npqu9Vlq9+vSVjTVqRXtKpo4IeQHxqKlYpFxX1rPdfu/hH7I//H7nWO63as+1bCKblSaldaXvplPXv9lZ/sf6r4aXxD2obujS4bd23CbxJs6t3ss7muTLWsoGxgy+wtzVsZW0u2vt+2aNvlcqfy3dvJ26XbZRURFa07THZs2vGlkld5p8q/qqlat3pd9ehOzs6bu3x3Ne7W2126+/PP/J/v7gnZ01xjVlO+F783d+/TffH7On9x+6W+Vqe2tPbrfsF+WV103fl61/r6A7oHNjagDdKGoYPzD944FHiotdGmcU+TZlPpYXBYevjFrym/9h4JP9Jx1O1o4zHTY9XH6cdLmpHm/ObhFl6LrDWptedE2ImONs+247/Z/rb/pOHJqlMapzaeJp8uOj1+puDMSLuw/dXZ9LMDHYs6HpxLPHf7/Nzz3RfCL1y6GHzxXKdf55lLXpdOXva4fOKK25WWqy5Xm7ucu45fc752vNulu/m66/XWG+432npm9Zy+6XPz7K3AWxdvM29fvTPnTk9vXO/dvvl9srucu8/vZd17cz/3/tiDVQ9xD0seqTwqf6z7uOZ3y9+bZC6yU/2B/V1PYp48GGAPvPxD/MeXwaKntKflzwye1T93eH5yKHjoxot5LwZfCl+OvSr+U/XP6tcWr4/95ftX13Di8OAb0Zvxt+vfab/b/97pfcdI1MjjD9kfxkZLPmp/rPvk9qnzc8LnZ2NLvhC+VHy1/Nr2Lfzbw/Hs8XEhS8SayAUw8IqmpQHwdj/ME5IAoN8AgKw0mVdPWCCT3wKQkb+rXP4vnsy95R0whwCNsIn0BcC5HYCjsDWFLQ3WKMixvgB1dFRUMFnEaY4wn4EFobTA1KR8fPwdzCcJlgB87RsfH2sZH/9aC78R7gPQ/mEyn5cbqxwEwLfQwc454tropVVy5Z/lPzaRFDnqunSQAAABnGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj42ODQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NDE8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4Kl/XR7QAAIpRJREFUeAHtfQ9YVNW69/Y4KChDgqKmGRl6JZMR8cN/ZQV0vqNZzWTW8djQjU6H8aknlXOPdbDsJlRe7JSiHR3/NZRgIqiMf0LNgQT/gFxABxUo0CECFBRsBprRGQ7fu9bae8+eYWbDIHnvp2s9PDNrr/W+73rXb71rrXevvd+hX2dnJ0MTRYAiQBGgCFAEKAL3HgK/u/e6THtMEaAIUAQoAhQBigBCgDoB1A4oAhQBigBFgCJwjyJAnYB7dOBptykCFAGKAEWAIkCdAGoDFAGKAEWAIkARuEcRoE7APTrwtNsUAYoARYAiQBGgTgC1AYoARYAiQBGgCNyjCFAn4B4deNptigBFgCJAEaAIUCeA2gBFgCJAEaAIUATuUQSoE3CPDjztNkWAIkARoAhQBKgTQG2AIkARoAhQBCgC9ygC1Am4RweedpsiQBGgCFAEKAISCgFFgCLwGyBgM9VVG41WhvHyChgx/H7/36AJKpIiQBH4/xUBS2tzi5mRDg+U/k9vwuInAabUmH5iSbHZZClHJFGbTS7HwlKuglogc1nrrrB3XO6kuSm32Swmk8VNpQfFYnIsdfFjN0x9+XibB/L6gFRMpe7E3w6vULa4HIdacRMSCu0+bypS+W2fAn/RFxttzuQ3ijJQld/2mNTbGnhLuRaEqNwKab9wQBsdsPv5aYeVjx1WTjvwTND2FxafPdvgrA+97msETOWbYb2J2Vze14Kd5d2xhpwbFlxX7kSL6+bSVkHZHc1W7cqYOnbDl2W3NZnuqMb/WxqzlabG+wQMHz16+KaSboavcmc8jLJqZyXoLsz3YVfEnQCG6X73tiISPzcqWa0/Qs3lm13WYzf0pLh3XKIiu1bqNy708/PZXNp9D7vyCkvE5Nhu1gJpnc2z7gul9yovplJ3Am+HVyhbXI5jragJCYX2IN/xKyEqrtBVOJFfP5XBemNtN52qPLy0omWv6WaHKzbrpT27lK9ca2GYgOgRC5cHKRYhR9+wsyQ2pOBUsysOWtbHCJhuwgHMnUh3rCGXnfn1Glpcf7lDfXWhgvkaWjxNVpfzwAU9LWIRsOgTY9dBXhYZFzLMRxwWq+kaEFy9htY1YV6cy6Na8ZMI6WvZnUqGIUSl6xVTl2ojUwpzl0y3t2EplcKF0V7gkJOGa1uaLIy3Z4ehveNyaLj7i0F+SHE4rO2eVJRCTI7vuK/PKE2MzxBRCX1eKaZSd43dDq9Qtrgcp1oxExIK7UG+P0dzQ3PYpAzFY0yKTNXfbGMrfTmi3n6jGeHL8G0JxFjOJcfC5ZC3v1O8Pp0leC/p7McLS7KLf/j0m/B9SwYLqGm2bxG43cncY23uWEMiGoW/qW36k8Xb37PFVUSgp1Vhb/zp4Pxb0gBq0R4i5z0IrUuR6pJclfgG7KHcXpJ3dxLAeQAg3msg0tyPcWX/oxlD6f74GMVkSP0mr0gtYE+IbA1HtqrVu4vZS0tD1vr4KEQEKSopNdf1bXjvuBACtsrcnaAGbiJKoVqxs6DGxV24rWFnUvzHX+uBYfHSvySlFhAaS0Pp+hUxUZOjIMXEr8mtFNy3udTcjRykCEm21mMZp3fnXELdt11L+3i/em/VhROF8S9ve3qmev7LGWl5VzlS9G1pMKhXps+fuW3+3G2Llx85XuXgWzWW/feK2K/mz/0qJnb/t2UNxXuPp3xRJlARS3KjUjOMjiIKjpX69ZusiEk6LOwar4Eb3j6GxU0rjDsTwuqJ6cDr75RpSarCwLPFzScrzztRoEvT2QMHY6LxE4QpGaqki1UOiN4o3qONmYJqo6fsSfi0us6lwVqqvkw6mLD44LrDVsZ6Cx9FBM/lPABoQxIYtvQ9p9lubSwtWBWTHh2d/kI0SK7i27U1FK1afPjLghuXcpFi0apj7/9Vm5B0uVlgyDdKj0FzyQfacYd6LOqv9a6eSzUUZakUk7FpTAazL6jl++h+NtkaUleoVmzOra3MTVIpYL7AfI7fzM16rJXTR0NpVjzMLUj9JkfFJOXW8K0AoaV0/3o0a0GQQrVmZy7f14aCVJVqRW5lTW5qEtuMIj63ll1OUBOW2p1JKsSnUMSv33+uWeyMx9ZauXMNzAOkBnCsWL+zspVFtQ8baijCOtfU5m6Gta6fKrUcQ+G2j6QXWWtUAA2an1Exa3YWCdBxy9hcckS9Vl1cbwHl41WqpNQi3BD7UbpzjUoVn1VOTpvdChGykLwISk7EzRUVOzadKWm6BeV1eScSV+pOnTfs/jhj/kz10zO3xa88ccnB3m6dPahbDEvf3G2w9KXsusiPMhJra83+bG/My1/BX+IXZVVVVV9+duTbMocFkG/dnS01FGxWxcTvF5gWKTlcwxmMpdYtziJV7u0TVHKnjLsqS20ubD5pUJ23cfmKNWDM3avN95zLmMqzYMRXbGZ3LlxsK0pNQiNeKbAdjr6b784eJ71aCbLkKSUOHOYSVNolRSbqrEBnLImEqsiUFsRTnywjdLLISFSMklKDqxxE9pKrs7MEa4jE2htglmkNjtI7O816OSLiUqTa2NnZUqLhrmWsmgyTmEN43WjuSo5DW6bLLzy0PnzOsVYoNV1WQp7926Scw+ZVWy4TltbSAr42mqNMPtJMaiu/2cPV8kIgs/WMidRzn65UqkhfxnYtUi7n+pagreZ4uG9XvH0PS9dWxE2om6HhlGe/jYVK6bYw1cnt8dvCpLs2FvLVjRkqKMlem5IdJt2mVJtxRWMGIkN/CsWuKJwJk+YcYpH5GbPg2qhUQhYWdqHB2mkuycJC2pAQo/7DKCwkSl8DdmQ8qcBy4tZcqqm/xTff2Wkzm2+Z0ZyA1FamYdsNC+MkS787io3NVLKLbYvo88S3z6FMVkYF4YVP0pdtS7NAvieioi45WUtnpz49jrONSM40ZDn1SE+x2WQscZhB/MxJyGF7yOuKM/W6RL4VbuYz6hIy9Vs0nAoMP/NkiQYsqCTFZTuROaTarOcsm9MAfzuvUUSZFn6lEqw/zLLqvm7ISedItGCK9REsiAcgkhsEGYukGCNpKKWkxViSgvsdV8Gjb60gMjOrwdLFhDgOFJps3HruAiUn4rINqbAobSpF84DkyRoV/dJWbrFKO8Ou72073uIWrhmb2NoZh34iCpt+SuBWPI4REb/wjx+dWoRLEVviAeG5HEpEcBapEkVPRBl3VdxgsRabXNLioCRWXVgi3Hb5vLk6nVh6CVnIgMusJwOHR5wHoEcZpkdUmIjXwIGFX8GVKRUtSKPqnGSkH9n4Sa0c7bJGvZqUN2F+a1MhUVpHroVCe8fV2UKcDHVhPRFWnYOXHrkGWu+SrIV4fUnOx8TWarKaLNPkY2JzoYYUKCvM4po7ynFqxnxZBcb90vdo7TVzTsBrBaTH59l9fev3cG29QqZBwleVeKG+eeYrsuunVQKoTReIW7BqD9LW2vLTupfIjEot67KsQ71D11p0ZNlNzCF7m7WE9Qnk+S78L0fe3wgWJw3FTUhUBye8wcqIE1Bbk4+30hXXWIqWfLQ3R12oLLQ7Aa26NLzdfneURaaW9QkUP4LX1qQj2/OBfRVIhrWpeGkYbMZp4FiwToDG1mku+zsq3BamrATnAKfWo4ncBg/lYVlLV5zM2H+p0mB3CKzVB3C7B3bk4ylsvrSD+CLKRrgmwrHMsjMVrU3G1u+xQEUK9jmgjSbcF2l+mbHTQ1FEQ/tnk45s/Msy2T6mx6ECeOQHu4HYbOKHTJ6sb0KdqMhMsM96ewMkZ0zHUz05n536hcRZT9BBdXUmnmiyZfkGNPNgWViGdVJqkEpkzQHJiVo9asaoT8C1KYXIdvMTsWnLEkrqodJarSN7YZcbFSCF/hTidUmpxh4O4FxNuNV61G4fNsSLUiZmVhjqjeZu+sj3AivS2VSiwV2UFxq7YSQNgRMAO2OiABZ7Z/HCK44wgkaQxFESEKLs+S1psFUTJ4Dk4XJ70S+ojtvXoz+6AFc1e/BqNmPPyVo0jNamHxNmoBVM9RVa0E5+hJ2GGdrzaDWzVR44DFXwp9xwGa4dk5gtCQBhmYQlIjiLVImiJ6KMSBUs4IXIt41MIaYoVJLoLSwheeLXCvItKdj2E7ntkx24SLWLRd0Rwa5X3T8OQHO7+yTTfb4kxN8bCIOfnoumfF7uZadjCSs+qcsrPl3eYLHBEen0jQa9TqcbxdjExHvAJZn5rlqdWaKaPooI9PG/D2WMLl9LlAzCTze8B6NnHKaKY+vgS6759LXZ+Cmy9/TXPtWggUo7/qOJEdPBQQ4wiCT86Gz49g2PB2KiRxfKkxbAsxVzxc/tbZWVR6AwYkriqxPwA+sBEa/K4yOgqOVktaUqp6yVYfwXPL5iPuqaxH/M0n9GB2Ehrj4cVKrUavLgDZTE/JVzgjGxJHzRag0aIW3ZZZDqlBx4fzNYHFrhNHBtQt3owDE7frf3fzBiwjQo21B1AVlhR92JHwwMMynm4eD7eGu7clADp4SShYee/j2LzIMvfzIJcekaDa31RzRAKVHsflYRAkVgr//nPxJhaCQ3yRk8nAMW5iXMKzlcwwS8EZW3Y8L97Hn/kN+vfFGTPnoaGjyGqblxfEPF6ldyF4Z+PeWFsxcQ4JaqY+gh0KT1c5Wz0YRhvMcq10yaBBntJcFJ5tQ9mrCIkCGB0iHTFUOg0qC5hOMdOuoKUV+YtyeGST0VBWzCVH5IA4/E4KZz7QK2j4tWJIHV+1mgjz2ZTbKcre+EBqJOhCj+BIwuZr2gvfKykoZWBPl01caSfJ1OPsrGmI6loZmnTvt0dhCaebAsfJqBzuTSsgv59UOWoFv5fChqRhr66pvIdnOLLjOW8i0fINPW7v8kfBRUSoKjlhD3Fwi6Jp9hM1NS1IWfq0aRgZL4DPdDVDetvEUAFH3QENt0XKZm5YKQoFFSb9E+8r3ISSQvsASGK5MTAEtpu+lGT8DBzY1SxCNYtu8qwp2xFexCd4oJi+dIe4YwqzPD9AQlnrhrJmKV4vVpGFbfMYnHZ8LbCq0nGm8wlu931QPxW1vlsx5EwygJHJeYOgUyxQcvtVnqvt5mhqfNSRnzHkVrX/8Jz/5hwxs+kBNJrmxJhBxmHWctXXFuPssaUteqng2BiDIuqyQ+XvjJ+sDbCA70n/cm8p4/yDguHPFly+YA5p4mpyeVnrLz9POC+cZtrl9XlU6MhBOqLUyaXIYeiMiVy+a+tPDlZ6L8RVXwhEs6e9GiAVnwTsDac3p9nh498idJtAWEoeHUCUSpjV2gyCYs6EqLsrBG9EwHPBY8s7tMxOhxeJPH9f2DYN5ntZz87+bZzM+opLgs9uUanvViMcresnbYsPv0nDzY3pHAh5+N0P0TE/D0XTJIJeLARE1+UFDrPTVayaSlXfnZyITzwyaoR9k7A4sQNNcmJD40Tkpzl20djHfwordLzmz48WDxrEejrny3G6qGvRjpzRj5JjvQo0xmaKgDMg/Mlp8/o21vMDK41jd4NCeTYcY890fykNJSigpbdtYexpXjZA+gXdqehoQ9N2fzcx0QgtpguFpZUndUW3tcB75FiXJJ4OkdTBE2tvNLsmKwhWG+Nvy+Qod9Q5IHsJsVOAmhkxQRJ+C9Ql11qDKE9GXI2wuHMky9p6LsOuIctivZvwn6GPR8dmcnoep+NslemRrISZQ8MFfOThmuiP+Whs+NY9K2pC2dm7YUdm35sgWKhYvkUbBkWMpLMQaLlQtyxnL0Rlwk8N0XzA3l6pgREeBdpeFLvM5Evjk7iK9kJkfOhYlrvxbkvINnx84bsFMdv7rk3GVtnn11END0SUNEnjx8AjtbLQbRPpLVcsbYAH5yS+Z8kt35Cdq3MnoADmkudN4rMiZNv25fxeo5oYz+y3XQP+WCp4J6iDCPQU9Q4om7ZqaF8wbBSIaPGAdLWuUVw7XmcrxS/fMvaXljOCaTEeVMHex8DBkf8aD9RVuZfDyzzeUQubclTrCbbxGcS5HXyfRiCMSUcWvzbvTztDg4en4ksy5vS5r+HwvCvSoy0YjLF0YKJkOPJfbRSYA8yG7D7tr2Dt1sbdJpkpX4uZc2bd1i+YwAr6iCZncMuLznXJbK+H5+M15avC4tLW/oUGVcQkpKAhKBHVPRNhgrFwoJhmnkklyplEfKhw2SwCrcG81dN9nhUIxX4cED+1u54xC4BWs3WcnfxKcCJob4BQxi54Z0yAABr6McQYXLbMjYAIdy3K6PL5xDiKU7CAsYsGsT6kYHd+pbGOnUF8Hdsu06eN3W/EM6rKYRIbAm2qz8WktYA4IckcF7v2Qwi0zAwyPdtYDKA/ARwpklR7JrCJm1sejUpvVF35bC8PT3lg55OHTCM689vW7fq/uzse+nvVTZ2sGwr0vB8mdrM5I/32ly34eifXx47do4i0CCH14YA5839hy3MM0VqC/Bj+B9sReiiJ7Cz9BgV33syWwaex+6rWOTZCCX6/odsmhzk16XvEwpgzq9dt0HsTPGBUStKYD7v0EstdE+8fzQzJNPHspjMXywvR2JF9eOZBDmxaZsb5KrtZewuZqseL9xMxZ/sE6rvT5UrkxITkH3246pTxpiRdrDFEX7KBk0DBgiHx1p7yKvkygjT0UygY/hs4AteRdNrcWHwERkCbHhSKYnQuDkqgcoObUsvIQ7FsElyUu8JP25+3qYzezi1i71i3jKb+KkwRJJfzQDpQM5GizA7g0L5OGse1viKXnDYRjeHERwFqnqDj0RZUSqeEUdM67UdqRwuPKPeBO996E9dLbVdC4nDbJxyqn4HNuBrAcXgoZ7QH07JJaG8lOVv4YsfGfHa+9oLK21F4u2J85drc37bG/5bJXd03dqoudcpotH0cFiZKI+Yzk5omQa9i+FOw/Y2LtLQ+9HtyFwGJj7SRRP21pTev4aEzJO2nMdeF63Gf6IE1Nca4JzMCYsNHBoPYye0V8ZvTdpIs97o8Zw8TozPti7/jvkLlcb2phJ3FLR1pjXzTEAK8Z6EzV54pRBFcqDbCk/gWzmviEO845lEHzdOVgEjTplxXVwIna49JVNfJI5c3zb6S98rrcwzLSYILhfh9NoLnXcRJtxY5GBedSOTGMRuvkaeJ8PqW06V8fM4m5uGnMPvrOB+cPfn0UPccADeFuh+7j/t+/teW/D1VVxVY/pJgQyHS1nK7a8zzDLJz4TDiPKJ68xTwRPY86dQQWDRyJjkyiyX/lPu7G1XyptvM6MCJYK9347+4T/C75KrWH3uW+ZetSX5ePv76UoXiZkiG2cKqtjZnN9bMiNf3M9o0hIlBX1ejYJm8B5U3lR8Y1BIe+s3fHOWk1rQ23Rge1zF6/Oe3dL+ZsfYgKZ7lhuFKcCHCGXFpxnRk3iAbzpEhTzL1eBGR47Wpbg55BI0tXLP2CBXT/YM/nETH3CglCy6h2O376a0QtJ+6IhoTyclxCH0k0fzT9cBqq83DrLEvxcBS5sBeuXf5brk7Dp3zG/G0ZcJ/iQzotNZNI+yM464GfOgvL4V2ehWvHWBfw42yOUnJkcru1384zp1yaoihgZ5EsKvT7f/8aT9lFuP3viZ+b+B3wtjXVAVtzSiqJu2VR98mcu6/Tt3paWzCakFvQrHsR2bPXnuPE1/+IW57Xz3FZ1MwQiyoQx59zY/JLZ/HIj7JtrtYUUznnvaGUys+XdrL3aMT6HoTL59ejebed9dBLgrJ+La8PRldHRM97dVQ51Em//4PA5r8IBIkrkoAZnu3x4wIVvESIjn2I9AMa0f/uXSJ7fQJEb3oFeaCMcPfkx+NSv1tiPJZoLYsdNfWLG1NNNtp7oQOSg5sRTpX7j0WuExFJTloIehjEBg353vwwdSremldl/Tqa56u2nD7z9xwPFTR0jHkVT58jb+RfYe0hL9qpjF4kU959EpTGTpgJJ2uIv+F9FMpXvTUY+gHz6WH933HcGlp6AJj407vTH5ZKHX14JmatfbQAfavQCeBbgkPwnhsP1jQ3//IlFlbFc2HsB7dPRDzzk7z8ZraFtWWlcWJ2t6uuPr57Xtd/irGnUg4Ph9wCe+dsjk4Cw+MRf0Q8IegfPwk8GPj26qUBo1u0XtFXYA5D6+QwJRcZmy9ZU82dgzQUHX3zqeNxTBoeoKaDi06hJsTBZis+/txz6ErTo90SJXoniZTJjpqA+arfvKGd9U1vu9o/gTvnyTS8ICIYqT2eTXbQwZzGsnBH9hOzdcuSBSfxHBc9R4RcI4K6wMwg9I2T0mm+KeI6CNbFTn3hi6hp7CV/lkJGOnCqDAu2OvWhJQclSvm7lapLt8uklRftC5FPRrAdgqtmvRieoTPdG6FlDXVqWiPZR+vAs9IaXvRe2hmP/uRQG4aKXb7BH4ATOUijBnVj9Siz0S5Y8LwTbu3jrzsreBkpY1NYVuXVgoCjd+nb9qVr4HjxQIhn2+DzIWb/JqEY1OJ36LOvPMUf/vLaG8R0aOhKKaj/fhZwBSG1VhX/7zEjyzp8itgTzDd/3p+86TVRoLU2bi4cYCRHBedi/9XIIRJQxubd54bpAuieitnP/Ha79Zz4Ps0e/LjZ2dR7DLHtxKlrPTbXlBQUFlQ3slHZgcHfR9V1BdyWCVxMFJCRYCL+Gypay4UPo7VYI9kP7PK61GjKJDvIEdU6OVp2IX0RmmHQUxOKYesVlrkgn8pWJ6nR46IAWCJIiU7R6PnaGb4mEYcgi5QmafIj6ykSLEaRI4E5Xk3eQ0TtTwCiuuaMcXjzOOEYHoEgB/Jew4XTGFi0bB/i3UqzbzX1sCM3W5C322uj3z+HalnX4ZVqICVz1j8MJbGgASEt1DhHEzTqq1MRFZspTMrVaDXmPmLwB7qitC97fBhYIP8OhGSz4guFmFRKakOjQdOmA8SQKEVTUkqAJsx7FAqA/BRsdR969V5AQwaZcNixQkb9vv35HIgkHQO//o0QCChBv/g7Nd3EkCkBKQgRR6IFCTV7Xt/20n40jwLGFbPweIlDmb9ec3LjmQByJIZRui0vHtm4uW0q0ivpue3rx9hWEPfXDHBs0y4YIcgpjVdAHF60AAZCNdmvulSheZif7jjFM0RSNJpGbMxAi2M1s6jpknUb8Ii2e9Xb5JGflJpdSnZmjzVTHkUC4uEzoh7maXRZkcYnpmekJrA4yLQ4CFL4mTWSRICPysnRTfiI7aZelZKancOq7jA4wp8MOCUmmhPmdnEAuUEFkXIq+xdp3DbGBBsIwRfE+thSmID1gDBJSNGp2ejLLcqC/4oxdddaRgAc4GE6v4AdBXAhPhjPdoORI7Do6IHzOnow9p1e9xMYB7qtFRm2uLiZLX/Rbh1Dta6R20yFc25R7iNS+8JZ23Uf2WOgXXEQHiNoSCUCDMV2WrE4hUSYIWBxAAeEhbnEWqRJFT0QZkSqAA2+L3Jv8ZlG1hduuME/Ggo1rgC4ns+HQJThsQMZdOg2Zy0sPQgQrcDyvUq13EGTGQa5CJ8BMQlTjUEyPQy0Ep7GTFo0MTolau7HaxfaOCwLP1OxOjmVHgq/BhRkndw2caCpUs0rIyM8YNGU6PiSUJ2RyXGKad5Fj7weEBQpDBIkToOSmB9j9C28VcJFlwPXLvvdR3C3/p3y/GP3AAEnWloz3UUAO/tuU8JEW/QLBjMMNXL3w21klY4XQJ4Jex6XoYHBcJmfezt8AFtjRhOA7DDdWSmhCqEBEB6dOGAvj0LbNOgGdnZX/hTbg1L/vR0sRJC66j+2+qSKX291JXF/2Rp09ls9sOInDArmQP0XxGRxQSnwLpYbH8Ocd6EcI+O258WgKCT7kGKEq7MDGHPCKudRU9qFCUCvd9WEWGwForsCOi+pnXjrLYyYxirvW2n/8ANf0QhSnBXybDWrWGyezQZ7ORtiKzqauQ8Y6AXjWC8STrLWpJJGc+rFTDna85AoOjhZ9pmOlPFPPzrwK/DMG6hKOlIs0VmrYVahCK1xSIhPw7s7XChWxNuU7rA7L1DptMlEnsbClDxsiooTbMKgh0keoNehS7PcsyBtIN3CjL8LI6cytUjCY7I2Qc/SviBAhRJAXR8mJ2EWI4IxU/jdO4I5le4Fdt9byYsEPpaAbmH3lXNBrZ2dD0WkVe5+zPvqlPaveQkGDybl2dr5pUVuycqHdeGDBq0pE3h5vPyI4i1SJoCeijEgVrEJILSUfuy6mttCchHkCCPeDAQz/8wB6HPrlcgrwGDpl+sE1mQl36NPSXHmxDv2omtegseNJUGEPWu4xl6W51nDd7OXlNxyCc9ATEktzg0ki9fd3GY1hMbWaGR+pj7eEfZhiAvYrRq9BfkMDRgTyTxqJgiI6dJHDdslSt/iR7OII2fHdT/paDIsfOVAcMeXk7sdNP11tMXcMCggYwz0G5CFoa75We9Us8fEJCPAL9B/AyTFeqPjF54ERDwcybW3/kvh6ezN1MWOzL4bIjuc8yT9I44WgTBeVmmsrrxitViszdOz4IKeuOXC64O1jWEhzXTR00sLpUkwHJ1IPL011lfDv/jqszOCHxg8d4vTQgGlvrG03M/19Bg25P1DwwLPbNizXq35sN6OzvwF+I4c8OMq7y/M6sNXrTcb+Pn6DA0ZIu7TbbQNCgtsUBc/p4R+aSXwGjR4VKFTTs9kkVMhVHiyw7jqa+oOGjg0JcnoUZaqtrIcjYD+/oSNGdZkVrqTxZTZTQ7XhOqwnIx4KFrdrsOzaGoPZ6uU3dPioQPR4AP6Tm8km8Q8UD1Fim/KkIV47YUa0j/CaFLzuIZEMChjd5f/KiTIKWxDL91xIT1G6sDX91U9a/rL39cVTBpN8/GGVMshyqbbNKhkwOmiYr9CYkG6WuqoWNMpS38BRfvxMa66pqzf7hEwaxrRB8PjvfH0HVG1NX8RJdtknEVsCowVL8vHxGz7K1bCK4CxSBafs7u1TRBmRKqd+daO2EzV3aanc6fPIK/ALxC25KqcZxZF0/33HnYDuVbpLKGyWW621F1RzTtSGyHQ5Tw5hnQCZbveT+LGxB91sK9M9OR/eARj+dekfH0VD3b57+TfJWWZm3uNFX0xxnmgeCKakFAGKAEWgFwh0WNraC1L2/X2bUegEkLyH4izqmVu3XmGeWK1Yu3AM8N44X7jgueJWhll5XKV4kLsR8lDoXU8O/wQXfmZj119Gx6Yx8JNBKwUv1nrad7qDeIpYT+nPb/v6z5+h9/4gWAyhbGPa4RMGzvPkOyX8jyMvZlxpejV8A8QNtn/fgt64YXw+XyGj4+c5nJSDIkARuD0E2i4vCs3BqxAzwIsckPVmZcNKeMs/Cd76ek1+QvbUFL+IEGvx92jZDHoj+lnqAbgfJf0W+dSl8D4gpMQ/34YHAPz9P/zwQySHpr5G4Nem5gvXrI9ETfxHyuMjwJ39180mQ2PgrPHR0xxOXHvWrM9jC4NH9G+t/clUfd78y0ivCEXIB5uenzWKe1O9Z1IoFUWAIkAR6AME/mWpvVDf+dB9yg/m/ft0dLLZdv264eqAxxSPBN/nyUMzrIp07PhnZvVvvXa95nx7g8HmHxEQ8x9PJakm0EMAkZH6ta7q+2teMx5//auchEektxXlRx8HiOBMqygCFAGKAEWAInA3I3BbHsTdDAztG0WAIkARoAhQBO52BKgTcLePMO0fRYAiQBGgCFAE3CBAnQA3wNBiigBFgCJAEaAI3O0IUCfgbh9h2j+KAEWAIkARoAi4QYA6AW6AocUUAYoARYAiQBG42xGgTsDdPsK0fxQBigBFgCJAEXCDAHUC3ABDiykCFAGKAEWAInC3I0CdgLt9hGn/KAIUAYoARYAi4AYB6gS4AYYWUwQoAhQBigBF4G5HgDoBd/sI0/5RBCgCFAGKAEXADQL/D4BaqFLDMQVOAAAAAElFTkSuQmCC"
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/ws/rest/user/[0-9]+/icon/[0-9]+\\.png"
    },
    "httpResponse": {
        "statusCode": 200,
        "headers": {
            "content-type": ["image/png"],
            "content-disposition": ["form-data; name=\"test.png\"; filename=\"test.png\""]
        },
        "body": {
            "type": "BINARY",
            "base64Bytes": "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"
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withDelay(TimeUnit.SECONDS, 10)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "SECONDS",
            "value": 10
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "SECONDS",
            "value": 10
        }
    }
}'

See REST API for full JSON specification

Distribution-based delays add realistic variability to response times. Each request samples a new random delay from the chosen distribution. Three distribution types are supported:

  • UNIFORM — equal probability across a min/max range; use for simple random variation
  • LOG_NORMAL — most values near the median with a long tail of slower responses; best for realistic network/API latency simulation. Specified via median and p99 (99th percentile)
  • GAUSSIAN — bell curve centered on the mean; use when you know the average latency and expected spread (standard deviation)

Distribution-based delays are supported on all action types including response, forward, error, template, and callback actions.

Sampled values are clamped to a minimum of 0 and a maximum of 86,400,000 milliseconds (24 hours). Validation constraints: UNIFORM requires min >= 0 and max >= min; LOG_NORMAL requires median > 0 and p99 >= median; GAUSSIAN requires mean >= 0 and stdDev >= 0.

// uniform random delay between 100ms and 500ms
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withDelay(Delay.uniform(TimeUnit.MILLISECONDS, 100, 500))
    );

// log-normal delay (realistic latency distribution) with median 200ms and p99 of 800ms
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withDelay(Delay.logNormal(TimeUnit.MILLISECONDS, 200, 800))
    );

// gaussian delay with mean 200ms and standard deviation of 50ms
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withDelay(Delay.gaussian(TimeUnit.MILLISECONDS, 200, 50))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// uniform random delay between 100ms and 500ms
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "UNIFORM",
                "min": 100,
                "max": 500
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

// log-normal delay with median 200ms and p99 of 800ms
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "LOG_NORMAL",
                "median": 200,
                "p99": 800
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

// gaussian delay with mean 200ms and standard deviation of 50ms
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "GAUSSIAN",
                "mean": 200,
                "stdDev": 50
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

# uniform random delay between 100ms and 500ms
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "UNIFORM",
                "min": 100,
                "max": 500
            }
        }
    }
}'

# log-normal delay with median 200ms and p99 of 800ms
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "LOG_NORMAL",
                "median": 200,
                "p99": 800
            }
        }
    }
}'

# gaussian delay with mean 200ms and standard deviation of 50ms
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body",
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "GAUSSIAN",
                "mean": 200,
                "stdDev": 50
            }
        }
    }
}'

See REST API for full JSON specification

MockServerClient mockServerClient = new MockServerClient("localhost", 1080);

// respond once with 200, then respond twice with 204, then
// respond with 404 as no remaining active expectations
mockServerClient
    .when(
        request()
            .withPath("/some/path"),
        Times.exactly(1)
    )
    .respond(
        response()
            .withStatusCode(200)
    );

mockServerClient
    .when(
        request()
            .withPath("/some/path"),
        Times.exactly(2)
    )
    .respond(
        response()
            .withStatusCode(204)
    );
var client = require('mockserver-client').mockServerClient("localhost", 1080);

// respond once with 200, then respond twice with 204, then
// respond with 404 as no remaining active expectations
client.mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "statusCode": 200
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}).then(
    function () {
        console.log("first expectation created");

        client.mockAnyResponse({
            "httpRequest": {
                "path": "/some/path"
            },
            "httpResponse": {
                "statusCode": 204
            },
            "times": {
                "remainingTimes": 2,
                "unlimited": false
            }
        }).then(
            function () {
                console.log("second expectation created");
            },
            function (error) {
                console.log(error);
            }
        );
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

# respond once with 200, then respond twice with 204, then
# respond with 404 as no remaining active expectations

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "statusCode": 200
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}'

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "statusCode": 204
    },
    "times": {
        "remainingTimes": 2,
        "unlimited": false
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withConnectionOptions(
                connectionOptions()
                    .withSuppressConnectionHeader(true)
                    .withSuppressContentLengthHeader(true)
            )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "suppressContentLengthHeader" : true,
            "suppressConnectionHeader" : true
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "suppressContentLengthHeader" : true,
            "suppressConnectionHeader" : true
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withConnectionOptions(
                connectionOptions()
                    .withKeepAliveOverride(false)
                    .withContentLengthHeaderOverride(10)
            )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "contentLengthHeaderOverride" : 10,
            "keepAliveOverride" : false
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "contentLengthHeaderOverride" : 10,
            "keepAliveOverride" : false
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withConnectionOptions(
                connectionOptions()
                    .withCloseSocket(true)
            )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "closeSocket" : true
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "closeSocket" : true
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_response_body")
            .withConnectionOptions(
                connectionOptions()
                    .withCloseSocket(true)
                    .withCloseSocketDelay(new Delay(MILLISECONDS, 500))
            )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "closeSocket" : true,
            "closeSocketDelay" : {
                "timeUnit" : "MILLISECONDS",
                "value" : 500
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_response_body",
        "connectionOptions" : {
            "closeSocket" : true,
            "closeSocketDelay" : {
                "timeUnit" : "MILLISECONDS",
                "value" : 500
            }
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        response()
            .withBody("some_long_response_body_delivered_in_chunks")
            .withConnectionOptions(
                connectionOptions()
                    .withChunkSize(10)
                    .withChunkDelay(new Delay(MILLISECONDS, 500))
            )
    );
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpResponse" : {
        "body" : "some_long_response_body_delivered_in_chunks",
        "connectionOptions" : {
            "chunkSize" : 10,
            "chunkDelay" : {
                "timeUnit" : "MILLISECONDS",
                "value" : 500
            }
        }
    }
}'

See REST API for full JSON specification

// $!request.headers['Session-Id'] returns an array of values because headers and queryStringParameters have multiple values
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        template(
            HttpTemplate.TemplateType.JAVASCRIPT,
            "return {\n" +
                "     'statusCode': 200,\n" +
                "     'cookies': {\n" +
                "          'session' : request.headers['Session-Id'][0]\n" +
                "     },\n" +
                "     'headers': {\n" +
                "          'Date' : Date()\n" +
                "     },\n" +
                "     'body': JSON.stringify(\n" +
                "               {\n" +
                "                    method: request.method,\n" +
                "                    path: request.path,\n" +
                "                    body: request.body\n" +
                "               }\n" +
                "          )\n" +
                "};"
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// $!request.headers['Session-Id'] returns an array of values because headers and queryStringParameters have multiple values
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "return { statusCode: 200, cookies: { session: request.headers[\"Session-Id\"] && request.headers[\"Session-Id\"][0] }, headers: { Date: [ Date() ] }, body: JSON.stringify({method: request.method, path: request.path, body: request.body}) };",
        "templateType": "JAVASCRIPT"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "return { statusCode: 200, cookies: { session: request.headers[\"Session-Id\"] && request.headers[\"Session-Id\"][0] }, headers: { Date: [ Date() ] }, body: JSON.stringify({method: request.method, path: request.path, body: request.body}) };",
        "templateType": "JAVASCRIPT"
    }
}'

See REST API for full JSON specification

To simplify handling different types of bodies, JavaScript and Velocity templates, have access to both an object request.body field and a string request.bodyAsString field which can be used as shown in the examples below.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        template(
            HttpTemplate.TemplateType.JAVASCRIPT,
            "return { statusCode: 200, headers: { Date: [ Date() ] }, body: JSON.stringify({is_active: JSON.parse(request.bodyAsString).is_active, id: \"1234\", name: \"taras\"}) };"
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "return { statusCode: 200, headers: { Date: [ Date() ] }, body: JSON.stringify({is_active: JSON.parse(request.bodyAsString).is_active, id: \"1234\", name: \"taras\"}) };",
        "templateType": "JAVASCRIPT"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "return { statusCode: 200, headers: { Date: [ Date() ] }, body: JSON.stringify({is_active: JSON.parse(request.bodyAsString).is_active, id: \"1234\", name: \"taras\"}) };",
        "templateType": "JAVASCRIPT"
    }
}'

See REST API for full JSON specification

String template = "" +
    "if (request.method === 'POST' && request.path === '/somePath') {\n" +
    "    return {\n" +
    "        'statusCode': 200,\n" +
    "        'body': JSON.stringify({name: 'value'})\n" +
    "    };\n" +
    "} else {\n" +
    "    return {\n" +
    "        'statusCode': 406,\n" +
    "        'body': request.body\n" +
    "    };\n" +
    "}";

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        template(HttpTemplate.TemplateType.JAVASCRIPT)
            .withTemplate(template)
            .withDelay(TimeUnit.MINUTES, 2)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {"path": "/some/path"},
    "httpResponseTemplate": {
        "template": "if (request.method === \"POST\" && request.path === \"/some/path\") { return { statusCode: 200, body: JSON.stringify({name: \"value\"}) }; } else { return { statusCode: 406, body: request.body }; }",
        "templateType": "JAVASCRIPT",
        "delay": {"timeUnit": "MINUTES", "value": 2}
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {"path": "/some/path"},
    "httpResponseTemplate": {
        "template": "if (request.method === \"POST\" && request.path === \"/some/path\") { return { statusCode: 200, body: JSON.stringify({name: \"value\"}) }; } else { return { statusCode: 406, body: request.body }; }",
        "templateType": "JAVASCRIPT",
        "delay": {"timeUnit": "MINUTES", "value": 2}
    }
}'

See REST API for full JSON specification

// $!request.headers['Session-Id'] and $!request.headers['User-Agent'] both returns an
// array of values because headers and queryStringParameters have multiple values
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        template(
            HttpTemplate.TemplateType.VELOCITY,
            "{\n" +
                "     \"statusCode\": 200,\n" +
                "     \"cookies\": { \n" +
                "          \"session\": \"$!request.headers['Session-Id'][0]\"\n" +
                "     },\n" +
                "     \"headers\": {\n" +
                "          \"Client-User-Agent\": [ \"$!request.headers['User-Agent'][0]\" ]\n" +
                "     },\n" +
                "     \"body\": $!request.body\n" +
                "}"
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// $!request.headers['Session-Id'] and $!request.headers['User-Agent'] both returns an
// array of values because headers and queryStringParameters have multiple values
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "{ \"statusCode\": 200, \"cookies\": { \"session\": \"$!request.headers[\"Session-Id\"][0]\" }, \"headers\": { \"Client-User-Agent\": [ \"$!request.headers[\"User-Agent\"][0]\" ] }, \"body\": \"$!request.body\" }",
        "templateType": "VELOCITY"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponseTemplate": {
        "template": "{ \"statusCode\": 200, \"cookies\": { \"session\": \"$!request.headers[\"Session-Id\"][0]\" }, \"headers\": { \"Client-User-Agent\": [ \"$!request.headers[\"User-Agent\"][0]\" ] }, \"body\": \"$!request.body\" }",
        "templateType": "VELOCITY"
    }
}'

See REST API for full JSON specification

public class CallbackActionExamples {

    public void responseClassCallback() {
        new ClientAndServer(1080)
            .when(
                request()
                    .withPath("/some.*")
            )
            .respond(
                callback()
                    .withCallbackClass(TestExpectationResponseCallback.class)
            );
    }

    public static class TestExpectationResponseCallback implements ExpectationResponseCallback {

        @Override
        public HttpResponse handle(HttpRequest httpRequest) {
            if (httpRequest.getPath().getValue().endsWith("/path")) {
                return response()
                    .withStatusCode(HttpStatusCode.ACCEPTED_202.code())
                    .withHeaders(
                        header("x-callback", "test_callback_header"),
                        header("Content-Length", "a_callback_response".getBytes(UTF_8).length),
                        header("Connection", "keep-alive")
                    )
                    .withBody("a_callback_response");
            } else {
                return notFoundResponse();
            }
        }
    }

}
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some.*"
    },
    "httpResponseClassCallback": {
        "callbackClass": "org.mockserver.examples.mockserver.CallbackActionExamples$TestExpectationResponseCallback"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some.*"
    },
    "httpResponseClassCallback" : {
        "callbackClass" : "org.mockserver.examples.mockserver.CallbackActionExamples$TestExpectationResponseCallback"
    }
}'

To use a class callback MockServer must be able to load the class from the classpath.

The callback class must:

  • implement
    • org.mockserver.mock.action.ExpectationResponseCallback to dynamically override the response
  • have a zero argument constructor
  • be available in the classpath of the MockServer

If MockServer is started using the the JUnit 4 @Rule, the JUnit 5 Test Extension, ClientAndServer or directly using org.mockserver.netty.MockServer then any class present in the main or test classpaths will be visible to MockServer.

If MockServer is started using the maven plugin only the non-forked goals (such as runAndWait and start) will be able to load classes from the main and test classpaths. It is possible to use classes from a separate maven dependency, however, this dependency must be specified in the plugin configuration dependencies section. Any dependency added to the plugin configuration dependencies section will then be visible to MockServer run using both forked and non-forked goals.

The following configuration shows how to use classes from a separate maven dependency in callback actions.

 <plugin>
     <groupId>org.mock-server</groupId>
     <artifactId>mockserver-maven-plugin</artifactId>
     <version>6.1.0</version>
     <configuration>
        <serverPort>1080</serverPort>
        <logLevel>DEBUG</logLevel>
        <pipeLogToConsole>true</pipeLogToConsole>
     </configuration>
     <executions>
         <execution>
             <id>pre-integration-test</id>
             <phase>pre-integration-test</phase>
             <goals>
                 <goal>runForked</goal>
             </goals>
         </execution>
         <execution>
             <id>post-integration-test</id>
             <phase>post-integration-test</phase>
             <goals>
                 <goal>stopForked</goal>
             </goals>
         </execution>
     </executions>
     <dependencies>
         <dependency>
             <groupId>com.my-domain</groupId>
             <artifactId>my-callback-dependency</artifactId>
             <version>1.0.0</version>
         </dependency>
     </dependencies>
 </plugin>

If MockServer is started using the command line then the callback classes must be added to the JVM using the classpath command line switch (cp or classpath). The classpath switch is ignored by the JVM if the jar switch is used. So to run the MockServer from the command line directly (with mockserver-netty-6.1.0-no-dependencies.jar) you must specify the org.mockserver.cli.Main main class specifically and not use the jar switch as follows.

java -Dfile.encoding=UTF-8 -cp mockserver-netty-6.1.0-no-dependencies.jar:my-callback-dependency.jar org.mockserver.cli.Main -serverPort 1080
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        new ExpectationResponseCallback() {
            @Override
            public HttpResponse handle(HttpRequest httpRequest) {
                if (httpRequest.getMethod().getValue().equals("POST")) {
                    return response()
                        .withStatusCode(ACCEPTED_202.code())
                        .withHeaders(
                            header("x-object-callback", "test_object_callback_header")
                        )
                        .withBody("an_object_callback_response");
                } else {
                    return notFoundResponse();
                }
            }
        }
    );
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        request -> {
            if (request.getMethod().getValue().equals("POST")) {
                return response()
                    .withStatusCode(ACCEPTED_202.code())
                    .withHeaders(
                        header("x-object-callback", "test_object_callback_header")
                    )
                    .withBody("an_object_callback_response");
            } else {
                return notFoundResponse();
            }
        }
    );
var mockServerClient = require('mockserver-client').mockServerClient;
var callback = function (request) {
    if (request.method === 'POST') {
        return {
            'statusCode': 201,
            'header': {
                "x-object-callback": ["test_object_callback_header"]
            },
            'body': "an_object_callback_response"
        };
    } else {
        return {
            'statusCode': 404
        };
    }
};
mockServerClient("localhost", 1080)
    .mockWithCallback(
        {
            'path': '/some/path'
        },
        callback
    )
    .then(
        function () {
            console.log("expectation created");
        },
        function (error) {
            console.log(error);
        }
    );

When using org.mockserver.client.MockServerClient each method / closure callback has a separate web socket client. To ensure the number of total threads does not grow too large for large numbers of method / closure callback expectations the default event loop thread pool for the web socket client is kept fairly low. However, if an extremely large load is matched against a single method / closure callback expectation the event loop thread pool may not be large enough for its web socket client.

The number of threads for the event loop thread pool for each web socket client (i.e. for each expectation with a method / closure callback) can be configured and is described in the configuration section.

MockServer provides an in-memory file store that can be used with the FileBody type. Files stored via the file store API can be referenced in expectations by name. The file store is cleared when MockServer is reset.

# Store a file
curl -v -X PUT "http://localhost:1080/mockserver/files/store?name=sample.json" \
    -H "Content-Type: application/json" \
    -d '{"id": 1, "name": "example"}'

# Retrieve a file
curl -v -X PUT "http://localhost:1080/mockserver/files/retrieve" \
    -H "Content-Type: application/json" \
    -d '{"name": "sample.json"}'

# List all stored files
curl -v -X PUT "http://localhost:1080/mockserver/files/list"

# Delete a file
curl -v -X PUT "http://localhost:1080/mockserver/files/delete" \
    -H "Content-Type: application/json" \
    -d '{"name": "sample.json"}'
MockServerClient mockServerClient = new MockServerClient("localhost", 1080);

// Store a file, then reference it in an expectation using FileBody
mockServerClient
    .when(
        request()
            .withPath("/api/data")
    )
    .respond(
        response()
            .withBodyFromFile("sample.json", MediaType.APPLICATION_JSON)
    );

Endpoints:

  • PUT /mockserver/files/store?name=<filename> — stores a file with the given name; the request body is the file content
  • PUT /mockserver/files/retrieve — retrieves a stored file; the request body is a JSON object with a "name" field
  • PUT /mockserver/files/list — lists all stored file names
  • PUT /mockserver/files/delete — deletes a stored file; the request body is a JSON object with a "name" field
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        new ExpectationResponseCallback() {
            @Override
            public HttpResponse handle(HttpRequest httpRequest) throws Exception {
                if (httpRequest.getMethod().getValue().equals("POST")) {
                    mockServerClient
                        .when(
                            request()
                                .withPath("/some/otherPath")
                        )
                        .respond(
                            response()
                                .withBody(httpRequest.getBodyAsString())
                        );
                    return response()
                        .withStatusCode(ACCEPTED_202.code())
                        .withBody("request processed");
                } else {
                    return notFoundResponse();
                }
            }
        }
    );
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .respond(
        httpRequest -> {
            if (httpRequest.getMethod().getValue().equals("POST")) {
                mockServerClient
                    .when(
                        request()
                            .withPath("/some/otherPath")
                    )
                    .respond(
                        response()
                            .withBody(httpRequest.getBodyAsString())
                    );
                return response()
                    .withStatusCode(ACCEPTED_202.code())
                    .withBody("request processed");
            } else {
                return notFoundResponse();
            }
        }
    );
var mockServerClient = require('mockserver-client').mockServerClient;
var callback = function (request) {
    if (request.method === 'POST') {
        mockServerClient("localhost", 1080)
            .mockAnyResponse({
                "httpRequest": {
                    "path": "/some/otherPath"
                },
                "httpResponse": {
                    "body": request.body.string
                }
            })
            .then(
                function () {
                    console.log("chained expectation created");
                },
                function (error) {
                    console.log(error);
                }
            );
        return {
            'statusCode': 202,
            'body': "request processed"
        };
    } else {
        return {
            'statusCode': 404
        };
    }
};
mockServerClient("localhost", 1080)
    .mockWithCallback(
        {
            'path': '/some/path'
        },
        callback
    )
    .then(
        function () {
            console.log("expectation created");
        },
        function (error) {
            console.log(error);
        }
    );

When using org.mockserver.client.MockServerClient each method / closure callback has a separate web socket client. To ensure the number of total threads does not grow too large for large numbers of method / closure callback expectations the default event loop thread pool for the web socket client is kept fairly low. However, if an extremely large load is matched against a single method / closure callback expectation the event loop thread pool may not be large enough for its web socket client.

The number of threads for the event loop thread pool for each web socket client (i.e. for each expectation with a method / closure callback) can be configured and is described in the configuration section.

 

A forward action can be:

  • either an exact forwarder, that forwards requests exactly as it receives them, containing the following:

  • or an overridden request (or overridden response), with a delay (including distribution-based delays), that allows any part of a forwarded request or response to be replaced or certain fields (path, headers, cookies or query parameters) to be modified

  • or a templated forwarder using javascript or velocity, with a delay, that allows requests to be modified or completely re-written before they are forwarded

  • or a callback used to dynamically generate the request to forward based on the request received by MockServer:

    • as a server side callback implemented as a java class that has a default constructor, implements org.mockserver.mock.action.ExpectationForwardCallback or org.mockserver.mock.action.ExpectationForwardAndResponseCallback and is available on the classpath

    • as a client side callback implemented as a closure using the java or javascript clients

The following code examples show how to create different forward actions.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forward()
            .withHost("mock-server.com")
            .withPort(80)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForward": {
        "host": "mock-server.com",
        "port": 80,
        "scheme": "HTTP"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForward": {
        "host": "mock-server.com",
        "port": 80,
        "scheme": "HTTP"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forward()
            .withHost("mock-server.com")
            .withPort(443)
            .withScheme(HttpForward.Scheme.HTTPS)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForward": {
        "host": "mock-server.com",
        "port": 443,
        "scheme": "HTTPS"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForward": {
        "host": "mock-server.com",
        "port": 443,
        "scheme": "HTTPS"
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withPath("/some/other/path")
                .withHeader("Host", "target.host.com")
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["target.host.com"]
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["target.host.com"]
            }
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withPath("/some/other/path")
                .withHeader("Host", "target.host.com"),
            response()
                .withBody("some_overridden_body")
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "httpResponse": {
            "body": "some_overridden_body"
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "httpResponse": {
            "body": "some_overridden_body"
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                // this replaces the entire set of headers
                .withHeader("Host", "target.host.com")
                .withBody("some_overridden_body"),
            requestModifier()
                .withPath("^/(.+)/(.+)$", "/prefix/$1/infix/$2/postfix")
                .withQueryStringParameters(
                    queryParametersModifier()
                        .add(
                            param("parameterToAddOne", "addedValue"),
                            param("parameterToAddTwo", "addedValue")
                        )
                        .replace(
                            param("overrideParameterToReplace", "replacedValue"),
                            param("requestParameterToReplace", "replacedValue"),
                            param("extraParameterToReplace", "shouldBeIgnore")
                        )
                        .remove(
                            "overrideParameterToRemove",
                            "requestParameterToRemove"
                        )

                )
                // this modifies the set of headers
                .withHeaders(
                    headersModifier()
                        .add(
                            header("headerToAddOne", "addedValue"),
                            header("headerToAddTwo", "addedValue")
                        )
                        .replace(
                            header("overrideHeaderToReplace", "replacedValue"),
                            header("requestHeaderToReplace", "replacedValue"),
                            header("extraHeaderToReplace", "shouldBeIgnore")
                        )
                        .remove(
                            "overrideHeaderToRemove",
                            "requestHeaderToRemove"
                        )

                )
                .withCookies(
                    cookiesModifier()
                        .add(
                            cookie("cookieToAddOne", "addedValue"),
                            cookie("cookieToAddTwo", "addedValue")
                        )
                        .replace(
                            cookie("overrideCookieToReplace", "replacedValue"),
                            cookie("requestCookieToReplace", "replacedValue"),
                            cookie("extraCookieToReplace", "shouldBeIgnore")
                        )
                        .remove(
                            "overrideCookieToRemove",
                            "requestCookieToRemove"
                        )

                )
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "requestOverride": {
            "headers": {
                "Host": [
                    "target.host.com"
                ]
            },
            "body": "some_overridden_body"
        },
        "requestModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            },
            "path": {
                "regex": "^/(.+)/(.+)$",
                "substitution": "/prefix/$1/infix/$2/postfix"
            },
            "queryStringParameters": {
                "add": {
                    "parameterToAddTwo": [
                        "addedValue"
                    ],
                    "parameterToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideParameterToRemove",
                    "requestParameterToRemove"
                ],
                "replace": {
                    "requestParameterToReplace": [
                        "replacedValue"
                    ],
                    "overrideParameterToReplace": [
                        "replacedValue"
                    ],
                    "extraParameterToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "requestOverride": {
            "headers": {
                "Host": [
                    "target.host.com"
                ]
            },
            "body": "some_overridden_body"
        },
        "requestModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            },
            "path": {
                "regex": "^/(.+)/(.+)$",
                "substitution": "/prefix/$1/infix/$2/postfix"
            },
            "queryStringParameters": {
                "add": {
                    "parameterToAddTwo": [
                        "addedValue"
                    ],
                    "parameterToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideParameterToRemove",
                    "requestParameterToRemove"
                ],
                "replace": {
                    "requestParameterToReplace": [
                        "replacedValue"
                    ],
                    "overrideParameterToReplace": [
                        "replacedValue"
                    ],
                    "extraParameterToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest()
            .withRequestOverride(
                request()
                    // this replaces the entire set of headers
                    .withHeader("Host", "target.host.com")
                    .withBody("some_overridden_body")
            )
            .withRequestModifier(
                requestModifier()
                    .withPath("^/(.+)/(.+)$", "/prefix/$1/infix/$2/postfix")
                    .withQueryStringParameters(
                        queryParametersModifier()
                            .add(
                                param("parameterToAddOne", "addedValue"),
                                param("parameterToAddTwo", "addedValue")
                            )
                            .replace(
                                param("overrideParameterToReplace", "replacedValue"),
                                param("requestParameterToReplace", "replacedValue"),
                                param("extraParameterToReplace", "shouldBeIgnore")
                            )
                            .remove(
                                "overrideParameterToRemove",
                                "requestParameterToRemove"
                            )

                    )
                    // this modifies the set of headers
                    .withHeaders(
                        headersModifier()
                            .add(
                                header("headerToAddOne", "addedValue"),
                                header("headerToAddTwo", "addedValue")
                            )
                            .replace(
                                header("overrideHeaderToReplace", "replacedValue"),
                                header("requestHeaderToReplace", "replacedValue"),
                                header("extraHeaderToReplace", "shouldBeIgnore")
                            )
                            .remove(
                                "overrideHeaderToRemove",
                                "requestHeaderToRemove"
                            )

                    )
                    .withCookies(
                        cookiesModifier()
                            .add(
                                cookie("cookieToAddOne", "addedValue"),
                                cookie("cookieToAddTwo", "addedValue")
                            )
                            .replace(
                                cookie("overrideCookieToReplace", "replacedValue"),
                                cookie("requestCookieToReplace", "replacedValue"),
                                cookie("extraCookieToReplace", "shouldBeIgnore")
                            )
                            .remove(
                                "overrideCookieToRemove",
                                "requestCookieToRemove"
                            )

                    )
            )
            .withResponseOverride(
                response()
                    .withBody("some_overridden_body")
            )
            .withResponseModifier(
                responseModifier()
                    .withHeaders(
                        headersModifier()
                            .add(
                                header("headerToAddOne", "addedValue"),
                                header("headerToAddTwo", "addedValue")
                            )
                            .replace(
                                header("overrideHeaderToReplace", "replacedValue"),
                                header("requestHeaderToReplace", "replacedValue"),
                                header("extraHeaderToReplace", "shouldBeIgnore")
                            )
                            .remove(
                                "overrideHeaderToRemove",
                                "requestHeaderToRemove"
                            )

                    )
                    .withCookies(
                        cookiesModifier()
                            .add(
                                cookie("cookieToAddOne", "addedValue"),
                                cookie("cookieToAddTwo", "addedValue")
                            )
                            .replace(
                                cookie("overrideCookieToReplace", "replacedValue"),
                                cookie("requestCookieToReplace", "replacedValue"),
                                cookie("extraCookieToReplace", "shouldBeIgnore")
                            )
                            .remove(
                                "overrideCookieToRemove",
                                "requestCookieToRemove"
                            )

                    )
            )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "requestOverride": {
            "headers": {
                "Host": [
                    "target.host.com"
                ]
            },
            "body": "some_overridden_body"
        },
        "requestModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            },
            "path": {
                "regex": "^/(.+)/(.+)$",
                "substitution": "/prefix/$1/infix/$2/postfix"
            },
            "queryStringParameters": {
                "add": {
                    "parameterToAddTwo": [
                        "addedValue"
                    ],
                    "parameterToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideParameterToRemove",
                    "requestParameterToRemove"
                ],
                "replace": {
                    "requestParameterToReplace": [
                        "replacedValue"
                    ],
                    "overrideParameterToReplace": [
                        "replacedValue"
                    ],
                    "extraParameterToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        },
        "responseOverride": {
            "body": "some_overridden_body"
        },
        "responseModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "requestOverride": {
            "headers": {
                "Host": [
                    "target.host.com"
                ]
            },
            "body": "some_overridden_body"
        },
        "requestModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            },
            "path": {
                "regex": "^/(.+)/(.+)$",
                "substitution": "/prefix/$1/infix/$2/postfix"
            },
            "queryStringParameters": {
                "add": {
                    "parameterToAddTwo": [
                        "addedValue"
                    ],
                    "parameterToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideParameterToRemove",
                    "requestParameterToRemove"
                ],
                "replace": {
                    "requestParameterToReplace": [
                        "replacedValue"
                    ],
                    "overrideParameterToReplace": [
                        "replacedValue"
                    ],
                    "extraParameterToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        },
        "responseOverride": {
            "body": "some_overridden_body"
        },
        "responseModifier": {
            "cookies": {
                "add": {
                    "cookieToAddOne": "addedValue",
                    "cookieToAddTwo": "addedValue"
                },
                "remove": [
                    "overrideCookieToRemove",
                    "requestCookieToRemove"
                ],
                "replace": {
                    "overrideCookieToReplace": "replacedValue",
                    "requestCookieToReplace": "replacedValue",
                    "extraCookieToReplace": "shouldBeIgnore"
                }
            },
            "headers": {
                "add": {
                    "headerToAddTwo": [
                        "addedValue"
                    ],
                    "headerToAddOne": [
                        "addedValue"
                    ]
                },
                "remove": [
                    "overrideHeaderToRemove",
                    "requestHeaderToRemove"
                ],
                "replace": {
                    "requestHeaderToReplace": [
                        "replacedValue"
                    ],
                    "overrideHeaderToReplace": [
                        "replacedValue"
                    ],
                    "extraHeaderToReplace": [
                        "shouldBeIgnore"
                    ]
                }
            }
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withPath("/some/other/path")
                .withHeader("Host", "any.host.com")
                .withSocketAddress("target.host.com", 1234, SocketAddress.Scheme.HTTPS)
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["any.host.com"]
            },
            "socketAddress": {
                "host": "target.host.com",
                "port": 1234,
                "scheme": "HTTPS"
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "headers": {
                "Host": ["any.host.com"]
            },
            "socketAddress": {
                "host": "target.host.com",
                "port": 1234,
                "scheme": "HTTPS"
            }
        }
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withHeader("Host", "target.host.com")
                .withBody("some_overridden_body")
        ).withDelay(SECONDS, 10)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "body": "some_overridden_body",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "delay": {
            "timeUnit": "SECONDS",
            "value": 10
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "body": "some_overridden_body",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "delay": {
            "timeUnit": "SECONDS",
            "value": 10
        }
    }
}'

See REST API for full JSON specification

Forward actions support the same distribution-based delays as response actions, allowing realistic latency simulation when proxying requests.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withHeader("Host", "target.host.com")
                .withBody("some_overridden_body")
        ).withDelay(Delay.logNormal(TimeUnit.MILLISECONDS, 200, 800))
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "body": "some_overridden_body",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "LOG_NORMAL",
                "median": 200,
                "p99": 800
            }
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "httpRequest": {
            "path": "/some/other/path",
            "body": "some_overridden_body",
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "delay": {
            "timeUnit": "MILLISECONDS",
            "distribution": {
                "type": "LOG_NORMAL",
                "median": 200,
                "p99": 800
            }
        }
    }
}'

See REST API for full JSON specification

// request.queryStringParameters['userId'] returns an array of values because headers and queryStringParameters have multiple values
String template = "return {\n" +
    "    'path' : \"/somePath\",\n" +
    "    'queryStringParameters' : {\n" +
    "        'userId' : request.queryStringParameters && request.queryStringParameters['userId']\n" +
    "    },\n" +
    "    'headers' : {\n" +
    "        'Host' : [ \"localhost:1081\" ]\n" +
    "    },\n" +
    "    'body': JSON.stringify({'name': 'value'})\n" +
    "};";

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        template(
            HttpTemplate.TemplateType.JAVASCRIPT,
            template
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// request.queryStringParameters['userId'] returns an array of values because headers and queryStringParameters have multiple values
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : \"/somePath\",\n" +
        "    'queryStringParameters' : {\n" +
        "        'userId' : request.queryStringParameters && request.queryStringParameters['userId']\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'body': JSON.stringify({'name': 'value'})\n" +
        "};",
        "templateType": "JAVASCRIPT"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : \"/somePath\",\n" +
        "    'queryStringParameters' : {\n" +
        "        'userId' : request.queryStringParameters && request.queryStringParameters['userId']\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'body': JSON.stringify({'name': 'value'})\n" +
        "};",
        "templateType": "JAVASCRIPT"
    }
}'

See REST API for full JSON specification

String template = "return {" + System.getProperty("line.separator") +
    "    'path' : request.path.substring(request.path.indexOf('/somePrefix')+'/somePrefix'.length,request.path.length)," + System.getProperty("line.separator") +
    "    'headers' : {" + System.getProperty("line.separator") +
    "        'Host' : [ \"localhost:1081\" ]" + System.getProperty("line.separator") +
    "    }," + System.getProperty("line.separator") +
    "};";

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/somePrefix*")
    )
    .forward(
        template(
            HttpTemplate.TemplateType.JAVASCRIPT,
            template
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/somePrefix*"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : request.path.substring(request.path.indexOf('/somePrefix')+'/somePrefix'.length,request.path.length),\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    }
        "};",
        "templateType": "JAVASCRIPT"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/somePrefix*"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : request.path.substring(request.path.indexOf('/somePrefix')+'/somePrefix'.length,request.path.length),\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    }\n" +
        "};",
        "templateType": "JAVASCRIPT"
    }
}'

See REST API for full JSON specification

// request.cookies['SessionId'] returns a single value because cookies only contain a single value
String template = "return {\n" +
    "    'path' : \"/somePath\",\n" +
    "    'cookies' : {\n" +
    "        'SessionId' : request.cookies && request.cookies['SessionId']\n" +
    "    },\n" +
    "    'headers' : {\n" +
    "        'Host' : [ \"localhost:1081\" ]\n" +
    "    },\n" +
    "    'keepAlive' : true,\n" +
    "    'secure' : true,\n" +
    "    'body' : \"some_body\"\n" +
    "};";

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        template(HttpTemplate.TemplateType.JAVASCRIPT)
            .withTemplate(template)
            .withDelay(TimeUnit.SECONDS, 20)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// request.cookies['SessionId'] returns a single value because cookies only contain a single value
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : \"/somePath\",\n" +
        "    'cookies' : {\n" +
        "        'SessionId' : request.cookies && request.cookies['SessionId']\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'keepAlive' : true,\n" +
        "    'secure' : true,\n" +
        "    'body' : \"some_body\"\n" +
        "};",
        "templateType": "JAVASCRIPT",
        "delay": {"timeUnit": "SECONDS", "value": 20}
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "return {\n" +
        "    'path' : \"/somePath\",\n" +
        "    'cookies' : {\n" +
        "        'SessionId' : request.cookies && request.cookies['SessionId']\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'keepAlive' : true,\n" +
        "    'secure' : true,\n" +
        "    'body' : \"some_body\"\n" +
        "};",
        "templateType": "JAVASCRIPT",
        "delay": {"timeUnit": "SECONDS", "value": 20}
    }
}'

See REST API for full JSON specification

// $!request.queryStringParameters['userId'] returns an array of values because headers and queryStringParameters have multiple values
String template = "{\n" +
    "    'path' : \"/somePath\",\n" +
    "    'queryStringParameters' : {\n" +
    "        'userId' : [ \"$!request.queryStringParameters['userId'][0]\" ]\n" +
    "    },\n" +
    "    'cookies' : {\n" +
    "        'SessionId' : \"$!request.cookies['SessionId']\"\n" +
    "    },\n" +
    "    'headers' : {\n" +
    "        'Host' : [ \"localhost:1081\" ]\n" +
    "    },\n" +
    "    'body': \"{'name': 'value'}\"\n" +
    "}";

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        template(
            HttpTemplate.TemplateType.VELOCITY,
            template
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
// $!request.queryStringParameters['userId'] returns an array of values because headers and queryStringParameters have multiple values
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "{\n" +
        "    'path' : \"/somePath\",\n" +
        "    'queryStringParameters' : {\n" +
        "        'userId' : [ \"$!request.queryStringParameters['userId'][0]\" ]\n" +
        "    },\n" +
        "    'cookies' : {\n" +
        "        'SessionId' : \"$!request.cookies['SessionId']\"\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'body': \"{'name': 'value'}\"\n" +
        "}",
        "templateType": "VELOCITY"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "template": "{\n" +
        "    'path' : \"/somePath\",\n" +
        "    'queryStringParameters' : {\n" +
        "        'userId' : [ \"$!request.queryStringParameters['userId'][0]\" ]\n" +
        "    },\n" +
        "    'cookies' : {\n" +
        "        'SessionId' : \"$!request.cookies['SessionId']\"\n" +
        "    },\n" +
        "    'headers' : {\n" +
        "        'Host' : [ \"localhost:1081\" ]\n" +
        "    },\n" +
        "    'body': \"{'name': 'value'}\"\n" +
        "}",
        "templateType": "VELOCITY"
    }
}'

See REST API for full JSON specification

A response template allows you to transform the response returned from the upstream server using a template that has access to both the original request and the upstream response. This is useful when you need to dynamically modify responses based on request context — for example, injecting request headers into the response body or conditionally changing the status code.

The template receives two objects: request (the original request) and response (the upstream response). The template must return a valid HTTP response JSON object.

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpOverrideForwardedRequest": {
        "requestOverride": {
            "headers": {
                "Host": ["target.host.com"]
            }
        },
        "responseTemplate": {
            "templateType": "JAVASCRIPT",
            "template": "return { 'statusCode': response.statusCode, 'headers': response.headers, 'body': JSON.stringify({ 'originalBody': response.body, 'requestPath': request.path }) };"
        }
    }
}'

See REST API for full JSON specification

When using a templated forward (JavaScript, Velocity, or Mustache), you can also specify a responseOverride and/or responseModifier to statically modify the response returned from the upstream server — without needing a separate response template.

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpForwardTemplate": {
        "templateType": "JAVASCRIPT",
        "template": "return { 'path': '/target' + request.path, 'headers': { 'Host': ['target.host.com'] } };",
        "responseOverride": {
            "headers": {
                "x-proxy": ["mockserver"]
            }
        }
    }
}'

See REST API for full JSON specification

public class CallbackActionExamples {

    public void forwardClassCallback() {
        new ClientAndServer(1080)
            .when(
                request()
                    .withPath("/some.*")
            )
            .forward(
                callback()
                    .withCallbackClass(TestExpectationForwardCallback.class)
            );
    }

    public static class TestExpectationForwardCallback implements ExpectationForwardCallback {

        @Override
        public HttpRequest handle(HttpRequest httpRequest) {
            return request()
                .withPath(httpRequest.getPath())
                .withMethod("POST")
                .withHeaders(
                    header("x-callback", "test_callback_header"),
                    header("Content-Length", "a_callback_request".getBytes(UTF_8).length),
                    header("Connection", "keep-alive")
                )
                .withBody("a_callback_request");
        }
    }

}
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some.*"
    },
    "httpForwardClassCallback": {
        "callbackClass": "org.mockserver.examples.mockserver.CallbackActionExamples$TestExpectationForwardCallback"
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some.*"
    },
    "httpForwardClassCallback" : {
        "callbackClass" : "org.mockserver.examples.mockserver.CallbackActionExamples$TestExpectationForwardCallback"
    }
}'

To use a class callback MockServer must be able to load the class from the classpath.

The callback class must:

  • implement
    • org.mockserver.mock.action.ExpectationForwardCallback to dynamically override the request or
    • org.mockserver.mock.action.ExpectationForwardAndResponseCallback to dynamically override the request and the response
  • have a zero argument constructor
  • be available in the classpath of the MockServer

If MockServer is started using the JUnit 4 @Rule, the JUnit 5 Test Extension, ClientAndServer or directly using org.mockserver.netty.MockServer then any class present in the main or test classpaths will be visible to MockServer.

If MockServer is started using the maven plugin only the non-forked goals (such as runAndWait and start) will be able to load classes from the main and test classpaths. It is possible to use classes from a separate maven dependency, however, this dependency must be specified in the plugin configuration dependencies section. Any dependency added to the plugin configuration dependencies section will then be visible to MockServer run using both forked and non-forked goals.

The following configuration shows how to use classes from a separate maven dependency in callback actions.

 <plugin>
     <groupId>org.mock-server</groupId>
     <artifactId>mockserver-maven-plugin</artifactId>
     <version>6.1.0</version>
     <configuration>
        <serverPort>1080</serverPort>
        <logLevel>DEBUG</logLevel>
        <pipeLogToConsole>true</pipeLogToConsole>
     </configuration>
     <executions>
         <execution>
             <id>pre-integration-test</id>
             <phase>pre-integration-test</phase>
             <goals>
                 <goal>runForked</goal>
             </goals>
         </execution>
         <execution>
             <id>post-integration-test</id>
             <phase>post-integration-test</phase>
             <goals>
                 <goal>stopForked</goal>
             </goals>
         </execution>
     </executions>
     <dependencies>
         <dependency>
             <groupId>com.my-domain</groupId>
             <artifactId>my-callback-dependency</artifactId>
             <version>1.0.0</version>
         </dependency>
     </dependencies>
 </plugin>

If MockServer is started using the command line then the callback classes must be added to the JVM using the classpath command line switch (cp or classpath). The classpath switch is ignored by the JVM if the jar switch is used. So to run the MockServer from the command line directly (with mockserver-netty-6.1.0-no-dependencies.jar) you must specify the org.mockserver.cli.Main main class specifically and not use the jar switch as follows.

java -Dfile.encoding=UTF-8 -cp mockserver-netty-6.1.0-no-dependencies.jar:my-callback-dependency.jar org.mockserver.cli.Main -serverPort 1080
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        new ExpectationForwardCallback() {
            @Override
            public HttpRequest handle(HttpRequest httpRequest) {
                return request()
                    .withPath(httpRequest.getPath())
                    .withMethod("POST")
                    .withHeaders(
                        header("x-callback", "test_callback_header"),
                        header("Content-Length", "a_callback_request".getBytes(UTF_8).length),
                        header("Connection", "keep-alive")
                    )
                    .withBody("a_callback_request");
            }
        }
    );
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        httpRequest -> request()
                    .withPath(httpRequest.getPath())
                    .withMethod("POST")
                    .withHeaders(
                        header("x-callback", "test_callback_header"),
                        header("Content-Length", "a_callback_request".getBytes(UTF_8).length),
                        header("Connection", "keep-alive")
                    )
                    .withBody("a_callback_request")
    );

When using org.mockserver.client.MockServerClient each method / closure callback has a separate web socket client. To ensure the number of total threads does not grow too large for large numbers of method / closure callback expectations the default event loop thread pool for the web socket client is kept fairly low. However, if an extremely large load is matched against a single method / closure callback expectation the event loop thread pool may not be large enough for its web socket client.

The number of threads for the event loop thread pool for each web socket client (i.e. for each expectation with a method / closure callback) can be configured and is described in the configuration section.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        new ExpectationForwardCallback() {
            @Override
            public HttpRequest handle(HttpRequest httpRequest) throws Exception {
                return request()
                    .withPath(httpRequest.getPath())
                    .withMethod("POST")
                    .withHeaders(
                        header("x-callback", "test_callback_header"),
                        header("Content-Length", "a_callback_request".getBytes(UTF_8).length),
                        header("Connection", "keep-alive")
                    )
                    .withBody("a_callback_request");
            }
        },
        new ExpectationForwardAndResponseCallback() {
            @Override
            public HttpResponse handle(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception {
                return httpResponse
                    .withHeader("x-response-test", "x-response-test")
                    .removeHeader(CONTENT_LENGTH.toString())
                    .withBody("some_overridden_response_body");
            }
        }
    );
new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .forward(
        httpRequest ->
            request()
                .withPath(httpRequest.getPath())
                .withMethod("POST")
                .withHeaders(
                    header("x-callback", "test_callback_header"),
                    header("Content-Length", "a_callback_request".getBytes(UTF_8).length),
                    header("Connection", "keep-alive")
                )
                .withBody("a_callback_request"),
        (httpRequest, httpResponse) ->
            httpResponse
                .withHeader("x-response-test", "x-response-test")
                .removeHeader(CONTENT_LENGTH.toString())
                .withBody("some_overridden_response_body")
    );

When using org.mockserver.client.MockServerClient each method / closure callback has a separate web socket client. To ensure the number of total threads does not grow too large for large numbers of method / closure callback expectations the default event loop thread pool for the web socket client is kept fairly low. However, if an extremely large load is matched against a single method / closure callback expectation the event loop thread pool may not be large enough for its web socket client.

The number of threads for the event loop thread pool for each web socket client (i.e. for each expectation with a method / closure callback) can be configured and is described in the configuration section.

 

An error action can return an invalid response as a sequence of bytes or drop the connection (with an optional delay)

The following code examples show how to create different error actions.

An error action can include a delay to simulate a service that hangs before dropping the connection, which is useful for testing timeout handling.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .error(
        error()
            .withDropConnection(true)
            .withDelay(TimeUnit.SECONDS, 5)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpError": {
        "dropConnection": true,
        "delay": {
            "timeUnit": "SECONDS",
            "value": 5
        }
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpError": {
        "dropConnection": true,
        "delay": {
            "timeUnit": "SECONDS",
            "value": 5
        }
    }
}'

See REST API for full JSON specification

// generate random bytes
byte[] randomByteArray = new byte[25];
new Random().nextBytes(randomByteArray);

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .error(
        error()
            .withDropConnection(true)
            .withResponseBytes(randomByteArray)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpError": {
        "dropConnection": true,
        "responseBytes": "eQqmdjEEoaXnCvcK6lOAIZeU+Pn+womxmg=="
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest": {
        "path": "/some/path"
    },
    "httpError": {
        "dropConnection": true,
        "responseBytes": "eQqmdjEEoaXnCvcK6lOAIZeU+Pn+womxmg=="
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withPath("/some/path")
    )
    .error(
        error()
            .withDropConnection(true)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpError" : {
        "dropConnection" : true
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "path" : "/some/path"
    },
    "httpError" : {
        "dropConnection" : true
    }
}'

See REST API for full JSON specification

Use respondBeforeBody on the request matcher to dispatch the configured response before MockServer reads the request body. The matcher must not include a body matcher and only RESPONSE and ERROR actions are supported. The connection is always closed after the response (the inbound body has not been consumed, so reuse is unsafe), so any closeSocket value is ignored — set keepAliveOverride(false) on the response if you want the Connection: close header on the wire. HTTP/1.1 only — HTTP/2 connections fall through to the standard pipeline. This is useful for reproducing client behaviour when a server responds and closes mid-upload.

new MockServerClient("localhost", 1080)
    .when(
        request()
            .withMethod("POST")
            .withPath("/upload")
            .withRespondBeforeBody(true)
    )
    .respond(
        response()
            .withStatusCode(403)
            .withBody("forbidden")
            .withConnectionOptions(
                connectionOptions().withKeepAliveOverride(false)
            )
    );
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
    "httpRequest" : {
        "method" : "POST",
        "path" : "/upload",
        "respondBeforeBody" : true
    },
    "httpResponse" : {
        "statusCode" : 403,
        "body" : "forbidden",
        "connectionOptions" : {
            "keepAliveOverride" : false
        }
    }
}'

See REST API for full JSON specification

 

LLM Response

An LLM response action (httpLlmResponse) returns a provider-correct response from a high-level description of what the model should say. Instead of hand-assembling Anthropic or OpenAI response JSON, you describe the intent (text, tool calls, usage, stop reason) and MockServer produces the byte-correct wire format.

Seven providers are supported: ANTHROPIC, OPENAI (Chat Completions), OPENAI_RESPONSES, GEMINI, BEDROCK, AZURE_OPENAI, and OLLAMA. At this milestone, ANTHROPIC and OPENAI have full codec support; the remaining providers are in progress and will return a structured 400 response with a list of currently supported providers.

Java Client Example

import static org.mockserver.client.LlmMockBuilder.llmMock;
import static org.mockserver.model.Completion.completion;
import static org.mockserver.model.Provider.ANTHROPIC;
import static org.mockserver.model.ToolUse.toolUse;
import static org.mockserver.model.Usage.usage;

// Simple text completion
llmMock("/v1/messages")
    .withProvider(ANTHROPIC)
    .withModel("claude-sonnet-4")
    .respondingWith(
        completion()
            .withText("The capital of France is Paris.")
            .withStopReason("end_turn")
            .withUsage(usage().withInputTokens(42).withOutputTokens(8))
    )
    .applyTo(mockServerClient);

// Tool / function call
llmMock("/v1/messages")
    .withProvider(ANTHROPIC)
    .respondingWith(
        completion()
            .withText("Let me check the weather.")
            .withToolCall(toolUse("get_weather").withArguments("{\"city\":\"Paris\"}"))
            .withStopReason("tool_use")
    )
    .applyTo(mockServerClient);

JSON Definition Format

{
    "httpRequest": {
        "method": "POST",
        "path": "/v1/messages"
    },
    "httpLlmResponse": {
        "provider": "ANTHROPIC",
        "model": "claude-sonnet-4",
        "completion": {
            "text": "The capital of France is Paris.",
            "stopReason": "end_turn",
            "usage": { "inputTokens": 42, "outputTokens": 8 }
        }
    }
}

Streaming with Realistic Timing

When streaming is enabled, MockServer expands the completion into provider-correct SSE events (e.g. message_start through message_stop for Anthropic, chat.completion.chunk deltas for OpenAI) with configurable timing physics.

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.mockserver.client.Llm.jitter;
import static org.mockserver.client.Llm.timeToFirstToken;
import static org.mockserver.client.Llm.tokensPerSecond;
import static org.mockserver.client.LlmMockBuilder.llmMock;
import static org.mockserver.model.Completion.completion;
import static org.mockserver.model.Provider.OPENAI;

llmMock("/v1/chat/completions")
    .withProvider(OPENAI)
    .withModel("gpt-4o")
    .respondingWith(
        completion()
            .withText("Streaming token by token...")
            .streaming()
            .withStreamingPhysics(
                timeToFirstToken(300, MILLISECONDS),
                tokensPerSecond(50),
                jitter(0.2))
    )
    .applyTo(mockServerClient);

Embeddings (Deterministic from Input)

For OpenAI embeddings, deterministicFromInput() generates reproducible vectors seeded from the input text. Same input + same dimensions + same seed produces an identical L2-normalised vector across JVMs.

import static org.mockserver.client.Llm.embedding;
import static org.mockserver.client.LlmMockBuilder.llmMock;
import static org.mockserver.model.Provider.OPENAI;

llmMock("/v1/embeddings")
    .withProvider(OPENAI)
    .respondingWith(
        embedding()
            .withDimensions(1536)
            .deterministicFromInput()
    )
    .applyTo(mockServerClient);

For multi-turn LLM conversations with stateful scenario progression, see the LLM Conversation example in the Stateful Scenarios section.

 

CRUD Simulation

CRUD Simulation lets you quickly stand up a fully functional RESTful resource without writing individual expectations for each HTTP method. You provide a base path and optional configuration, and MockServer automatically generates five endpoints that manage an in-memory collection of JSON objects.

This is useful when your tests need a realistic data store (e.g. users, products, orders) that supports create, read, update, and delete operations without manually defining expectations for each verb.

Auto-Generated Endpoints

Given a basePath of /api/users, MockServer generates:

MethodPathDescriptionSuccess Status
GET/api/usersList all items200
POST/api/usersCreate a new item201
GET/api/users/{id}Get item by ID200
PUT/api/users/{id}Update item by ID200
DELETE/api/users/{id}Delete item by ID204

JSON Definition Format

A CRUD simulation is defined by a JSON object with the following fields:

  • basePath (required) - the URL path prefix for the generated endpoints, e.g. /api/users
  • idField (optional, default "id") - the field name used as the unique identifier in each JSON object
  • idStrategy (optional, default "AUTO_INCREMENT") - how IDs are generated for new items:
    • AUTO_INCREMENT - sequential numeric IDs (1, 2, 3, ...)
    • UUID - random UUID strings
  • initialData (optional) - an array of JSON objects to pre-populate the data store

REST API

Register a CRUD simulation using PUT /mockserver/crud:

curl -X PUT "http://localhost:1080/mockserver/crud" \
  -H "Content-Type: application/json" \
  -d '{
    "basePath": "/api/users",
    "idField": "id",
    "idStrategy": "AUTO_INCREMENT",
    "initialData": [
      {"name": "Alice", "email": "alice@example.com"},
      {"name": "Bob", "email": "bob@example.com"}
    ]
  }'

After registration, the endpoints are immediately available:

# List all users
curl http://localhost:1080/api/users

# Create a new user
curl -X POST http://localhost:1080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Charlie", "email": "charlie@example.com"}'

# Get user by ID
curl http://localhost:1080/api/users/1

# Update user
curl -X PUT http://localhost:1080/api/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice Updated", "email": "alice@example.com"}'

# Delete user
curl -X DELETE http://localhost:1080/api/users/3

Java Client Example

new MockServerClient("localhost", 1080)
    .crud(
        new CrudExpectationsDefinition()
            .withBasePath("/api/users")
            .withIdField("id")
            .withIdStrategy(CrudExpectationsDefinition.IdStrategy.AUTO_INCREMENT)
    );

UUID ID Strategy Example

curl -X PUT "http://localhost:1080/mockserver/crud" \
  -H "Content-Type: application/json" \
  -d '{
    "basePath": "/api/products",
    "idStrategy": "UUID"
  }'

# Create a product - ID will be a UUID like "550e8400-e29b-41d4-a716-446655440000"
curl -X POST http://localhost:1080/api/products \
  -H "Content-Type: application/json" \
  -d '{"name": "Widget", "price": 9.99}'

CRUD simulations are independent of regular expectations and are cleared when MockServer is reset. You can register multiple CRUD simulations with different base paths simultaneously.

2. Run Your Test Scenarios

With MockServer running and expectations configured, execute your application or test suite. Your application should make requests to MockServer (on the configured port) instead of the real dependencies. MockServer will match incoming requests against the configured expectations and return the specified responses.

 

3. Verify Requests

MockServer supports verification of requests it has received, including both proxied requests and requests that have matched an expectation.

Verification can be specified as follows:

 

How Verification Works

MockServer records all received requests in an in-memory event log (separate from application logs). Verification checks this event log:

For request matcher count verification: MockServer filters the event log to find all RECEIVED_REQUEST entries matching your request matcher, counts them, and compares the count against your constraint (atLeast(n), exactly(n), etc.). Returns HTTP 202 if the count matches, or HTTP 406 with an error message if it does not.

For expectation ID verification: MockServer retrieves all events associated with the specified expectation ID (including EXPECTATION_RESPONSE and FORWARDED_REQUEST entries) and verifies the count.

For sequence verification: MockServer scans recorded requests in order, checking that each expected request appears after the previous match. This is not a simple count comparison—order matters.

Important notes for parallel testing:

  • The event log size is bounded by the maxLogEntries configuration property (default: minimum of free heap KB / 8 and 100,000 entries—see configuration). When this limit is reached, the oldest entries are evicted. If you run many parallel tests generating thousands of requests, consider increasing this value.
  • Event recording uses an asynchronous ring buffer. However, verification operations are serialized through the same ring buffer in FIFO order, so a request that has reached MockServer and been recorded will be visible to subsequent verification calls. Intermittent failures are more commonly caused by:
    • Your application under test sending requests asynchronously—ensure the application has completed sending before you verify
    • Cross-test interference—one test's requests appearing in another test's verification
    • Log eviction due to high request volume exceeding maxLogEntries
  • Best practices for parallel tests:
    • Use separate MockServer instances (different ports or containers) per test for complete isolation
    • If sharing an instance, use unique paths per test (e.g., /test/{testId}/...) or unique headers/query parameters in matchers
    • Avoid broad matchers like only path("/api") in parallel tests
    • Be careful with clear() or reset()—they affect all tests sharing the instance
    • If verification fails intermittently because your system under test is asynchronous, use retry-with-backoff to wait for requests to arrive (not to wait for MockServer to process already-received requests)
  • To retrieve recorded requests for debugging, use PUT /mockserver/retrieve?type=REQUESTS or mockServerClient.retrieveRecordedRequests(null).

For more details on the internal architecture, see the Event System documentation.

 

Verification Timing

Note: MockServer processes log entries asynchronously using a ring buffer. When calling verify() immediately after sending requests, there may be a brief delay before log entries are available for verification. If verification fails unexpectedly right after requests are sent, add a small delay (e.g., 100ms) before retrying. This is most commonly needed in high-throughput scenarios or when the system under test sends requests asynchronously.

Verifying Repeating Requests

Verify that a request has been received by MockServer a specific number of times using a Verification

new MockServerClient("localhost", 1080)
    .verify(
        request()
            .withPath("/some/path"),
        VerificationTimes.atLeast(2)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
  .verify(
    {
      'path': '/some/path'
    }, 2)
  .then(
    function () {
      console.log("request found at least 2 times");
    },
    function (error) {
      console.log(error);
    }
  );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "path": "/simple"
    },
    "times": {
        "atLeast": 2
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
.verify(
    request()
        .withPath("/some/path"),
    VerificationTimes.atMost(2)
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
.verify(
{
  'path': '/some/path'
}, 0, 2)
.then(
function () {
  console.log("request found at most 2 times");
},
function (error) {
  console.log(error);
}
);

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "path": "/simple"
    },
    "times": {
        "atMost": 2
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        request()
            .withPath("/some/path"),
        VerificationTimes.exactly(2)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
  .verify(
    {
      'path': '/some/path'
    }, 2, 2)
    .then(
        function () {
            console.log("request found exactly 1 time");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "path": "/simple"
    },
    "times": {
        "atLeast": 2,
        "atMost": 2
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        openAPI(
            "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json"
        ),
        VerificationTimes.atLeast(2)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
    .verify(
        {
            'specUrlOrPayload': 'https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json'
        }, 2)
    .then(
        function () {
            console.log("request found exactly 2 times");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json"
    },
    "times": {
        "atLeast": 2
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        openAPI(
            "org/mockserver/openapi/openapi_petstore_example.json",
            "showPetById"
        ),
        VerificationTimes.once()
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
    .verify(
        {
            'specUrlOrPayload': 'org/mockserver/openapi/openapi_petstore_example.json',
            'operationId': 'showPetById'
        }, 1, 1)
    .then(
        function () {
            console.log("request found exactly 2 times");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "specUrlOrPayload": "org/mockserver/openapi/openapi_petstore_example.json",
        "operationId": "showPetById"
    },
    "times": {
        "atLeast": 1,
        "atMost": 1
    }
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        "31e4ca35-66c6-4645-afeb-6e66c4ca0559",
        VerificationTimes.once()
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
    .verifyById(
        {
            'id': '31e4ca35-66c6-4645-afeb-6e66c4ca0559'
        }, 1, 1)
    .then(
        function () {
            console.log("request found exactly 1 time");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
            "id": "31e4ca35-66c6-4645-afeb-6e66c4ca0559"
        }'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        request()
            .withPath("/some/path"),
        VerificationTimes.exactly(0)
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
  .verify(
    {
      'path': '/some/path'
    }, 0, true)
  .then(
    function () {
      console.log("request found zero times");
    },
    function (error) {
      console.log(error);
    }
  );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "path": "/simple"
    },
    "times": {
        "atMost": 0
    }
}'

See REST API for full JSON specification

Verifying Request Sequences

Verify that a sequence of requests has been received by MockServer in the specified order using a VerificationSequence

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

new MockServerClient("localhost", 1080)
    .verify(
        request()
            .withPath("/some/path/one"),
        request()
            .withPath("/some/path/two"),
        request()
            .withPath("/some/path/three")
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
  .verifySequence(
    {
      'path': '/some/path/one'
    },
    {
      'path': '/some/path/two'
    },
    {
      'path': '/some/path/three'
    }
  )
  .then(
    function () {
      console.log("request sequence found in the order specified");
    },
    function (error) {
      console.log(error);
    }
  );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verifySequence" -d '{
   "httpRequests":[
      {
         "path":"/some/path/one"
      },
      {
         "path":"/some/path/two"
      },
      {
         "path":"/some/path/three"
      }
   ]
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        request()
            .withPath("/status"),
        openAPI(
            "org/mockserver/openapi/openapi_petstore_example.json",
            "listPets"
        ),
        openAPI(
            "org/mockserver/openapi/openapi_petstore_example.json",
            "showPetById"
        )
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
    .verifySequence(
        {
            'path': '/status'
        },
        {
            'specUrlOrPayload': 'org/mockserver/openapi/openapi_petstore_example.json',
            'operationId': 'listPets'
        },
        {
            'specUrlOrPayload': 'org/mockserver/openapi/openapi_petstore_example.json',
            'operationId': 'showPetById'
        }
    )
    .then(
        function () {
            console.log("request sequence found in the order specified");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verifySequence" -d '{
   "httpRequests":[
      {
         "path": "/status"
      },
      {
         "specUrlOrPayload": "org/mockserver/openapi/openapi_petstore_example.json",
         "operationId": "listPets"
      },
      {
         "specUrlOrPayload": "org/mockserver/openapi/openapi_petstore_example.json",
         "operationId": "showPetById"
      }
   ]
}'

See REST API for full JSON specification

new MockServerClient("localhost", 1080)
    .verify(
        "31e4ca35-66c6-4645-afeb-6e66c4ca0559",
        "66c6ca35-ca35-66f5-8feb-5e6ac7ca0559",
        "ca3531e4-23c8-ff45-88f5-4ca0c7ca0559"
    );
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080)
    .verifySequenceById(
        {
            'id': '31e4ca35-66c6-4645-afeb-6e66c4ca0559'
        },
        {
            'id': '66c6ca35-ca35-66f5-8feb-5e6ac7ca0559'
        },
        {
            'id': 'ca3531e4-23c8-ff45-88f5-4ca0c7ca0559'
        }
    )
    .then(
        function () {
            console.log("request sequence found in the order specified");
        },
        function (error) {
            console.log(error);
        }
    );

See REST API for full JSON specification

curl -v -X PUT "http://localhost:1080/mockserver/verifySequence" -d '{
    "httpRequests": [
        {
            "id": "31e4ca35-66c6-4645-afeb-6e66c4ca0559"
        },
        {
            "id": "66c6ca35-ca35-66f5-8feb-5e6ac7ca0559"
        },
        {
            "id": "ca3531e4-23c8-ff45-88f5-4ca0c7ca0559"
        }
    ]
}'

See REST API for full JSON specification

 

Spring Boot Compatibility

MockServer targets Java 11 as the minimum supported version and uses the javax namespace throughout. This means MockServer is compatible with Spring Boot 2.x (which uses Spring Framework 5.x) but is not compatible with Spring Boot 3.x (which uses Spring Framework 6.x).

Spring Boot 3 requires Java 17+ and migrated from the javax namespace to the jakarta namespace. If your project uses Spring Boot 3, you can still use MockServer as a standalone Docker container or process, but the Spring Test Execution Listener and JUnit integrations that depend on Spring classpath integration are not supported.

Spring Boot Version Spring Framework Namespace MockServer Compatible
2.x 5.x javax Yes
3.x 6.x jakarta No (use Docker or standalone)
 

Upgrading MockServer

When upgrading MockServer between versions, be aware of the following changes that may affect your setup:

  • Java 11 minimum (since 5.14.0) - MockServer requires Java 11 or later. If you are running on Java 8, you must upgrade your JVM before upgrading MockServer.
  • JSON Schema validator version change - the underlying JSON Schema validation library was updated in recent versions. If you use JSON Schema body matchers with custom schemas, verify they still validate correctly after upgrading.
  • Expectation JSON format - the JSON format for expectations has evolved between major versions. If you use JSON expectation initializer files (MOCKSERVER_INITIALIZATION_JSON_PATH), test your initializer files against the new version before deploying. Fields that were previously accepted may be rejected or interpreted differently.

It is recommended to run your full test suite after upgrading to catch any compatibility issues early.

 

HTTP/2 Proxy Limitations

MockServer can accept HTTP/2 connections and serve mock responses over HTTP/2. However, when MockServer is used as a proxy and forwards requests to downstream services, HTTP/2 requests are downgraded to HTTP/1.1. This means:

  • Mocking with HTTP/2 - works correctly. Clients can connect to MockServer using HTTP/2 and receive mock responses.
  • Proxying with HTTP/2 - the forwarded request to the downstream service will be sent as HTTP/1.1, regardless of the original protocol version. The response returned to the client will also be HTTP/1.1.

If your tests require end-to-end HTTP/2 proxying (including HTTP/2 to the upstream server), this is not currently supported. Consider using MockServer in mock mode instead of proxy mode for HTTP/2 endpoints.

 

Single Port Architecture

MockServer serves both mock and proxy traffic on the same port (default 1080). There is no separate port for proxying. The proxyRemotePort and proxyRemoteHost settings specify the upstream target server that unmatched requests are forwarded to — they do not open a separate listening port. All expectations, proxy forwarding, and protocol support (HTTP, HTTPS, SOCKS) share the single serverPort.