An expectation can also run extra webhooks or callbacks before or after its response — see Before & After Actions for mirroring, fan-out, shadow, and gating patterns.
Please Note: There are over 100 more detailed code examples in Java, JavaScript, Python, Ruby, Go, .NET, Rust, PHP 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, Python, Ruby, Go, .NET, Rust, PHP and the REST API below.
The Node client supports two styles. The fluent when().respond() DSL is the recommended style — it mirrors the Java client and makes the request matcher, times, and priority explicit:
var mockServerClient = require('mockserver-client').mockServerClient;
// Recommended: fluent when().respond() DSL
mockServerClient("localhost", 1080)
.when({
method: 'POST',
path: '/login',
body: { username: 'foo', password: 'bar' }
})
.withTimes(1)
.withPriority(10)
.respond({
statusCode: 302,
headers: { Location: ['https://www.mock-server.com'] },
cookies: { sessionId: '2By8LOhBmaW5nZXJwcmludCIlMDAzMW' }
})
.then(
function () { console.log("expectation created"); },
function (error) { console.log(error); }
);
.withTimes(n) limits the expectation to n matched requests. .withTimeToLive({ unlimited: false, timeToLive: 60, timeUnit: 'SECONDS' }) sets an expiry window. .withPriority(n) controls evaluation order (higher value wins). The terminal actions are .respond(), .forward(), .error(), and .callback().
The procedural mockAnyResponse style passes the full expectation JSON directly and is still supported:
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);
}
);
from mockserver import MockServerClient, HttpRequest, HttpResponse
client = MockServerClient("localhost", 1080)
client.when(
HttpRequest(
method="POST",
path="/login",
body="{username: 'foo', password: 'bar'}"
)
).respond(
HttpResponse(
status_code=302,
headers={"Location": ["https://www.mock-server.com"]}
)
)
require 'mockserver-client'
include MockServer
client = MockServer::Client.new('localhost', 1080)
client.when(
HttpRequest.new(
method: 'POST',
path: '/login',
body: "{username: 'foo', password: 'bar'}"
)
).respond(
HttpResponse.new(
status_code: 302,
headers: { 'Location' => ['https://www.mock-server.com'] }
)
)
import mockserver "github.com/mock-server/mockserver-monorepo/mockserver-client-go/v7"
client := mockserver.New("localhost", 1080)
client.When(
mockserver.Request().
Method("POST").
Path("/login").
Body("{username: 'foo', password: 'bar'}"),
).Respond(
mockserver.Response().
StatusCode(302).
Header("Location", "https://www.mock-server.com"),
)
using MockServer.Client;
using MockServer.Client.Models;
using var client = new MockServerClient("localhost", 1080);
client.When(
HttpRequest.Request()
.WithMethod("POST")
.WithPath("/login")
.WithBody("{username: 'foo', password: 'bar'}")
).Respond(
HttpResponse.Response()
.WithStatusCode(302)
.WithHeader("Location", "https://www.mock-server.com")
);
use mockserver_client::{ClientBuilder, HttpRequest, HttpResponse};
let client = ClientBuilder::new("localhost", 1080).build().unwrap();
client.when(
HttpRequest::new()
.method("POST")
.path("/login")
.body("{username: 'foo', password: 'bar'}"),
).respond(
HttpResponse::new()
.status_code(302)
.header("Location", "https://www.mock-server.com"),
).unwrap();
use MockServer\MockServerClient;
use MockServer\HttpRequest;
use MockServer\HttpResponse;
$client = new MockServerClient('localhost', 1080);
$client->when(
HttpRequest::request()
->method('POST')
->path('/login')
->body("{username: 'foo', password: 'bar'}")
)->respond(
HttpResponse::response()
->statusCode(302)
->header('Location', 'https://www.mock-server.com')
);
To use the Java client add the org.mock-server:mockserver-client-java-no-dependencies:{{ site.mockserver_version }} 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>{{ site.mockserver_version }}</version>
</dependency>
A request matcher expectation may contain:
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.
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.
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.
MockServer can model multi-step, stateful API behaviour — where the response to a request depends on what happened before. This covers named state-machine scenarios (using scenarioName / scenarioState / newScenarioState), sequential / cycling responses (httpResponses + responseMode), timed and externally-triggered state transitions, and cross-protocol scenario correlation.
These features have their own page with a feature overview and runnable examples for every client — Java, JavaScript, Python, Ruby, Go, .NET, Rust, PHP, the REST API and JSON:
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.
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:
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:
Matching for key to multiple values supports multiple values for each key for headers, query parameters and path parameters
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:
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:
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:
Example - match a GraphQL query:
import static org.mockserver.model.GraphQLBody.graphQL;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(graphQL("{ user(id: 1) { name email } }"))
)
.respond(
response()
.withStatusCode(200)
.withBody("{\"data\": {\"user\": {\"name\": \"Alice\", \"email\": \"alice@example.com\"}}}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"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\"}}}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"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\"}}}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"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\"}}}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"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\"}}}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""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\""}}}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"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\"}}}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"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\"}}}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"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\"}}}"
}
}'
See REST API for full JSON specification
Example - match with operation name and variables schema:
import static org.mockserver.model.GraphQLBody.graphQL;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(
graphQL(
"query GetUser($id: ID!) { user(id: $id) { name email } }",
"GetUser",
"{\"type\": \"object\", \"properties\": {\"id\": {\"type\": \"string\"}}, \"required\": [\"id\"]}"
)
)
)
.respond(
response()
.withStatusCode(200)
.withBody("{\"data\": {\"user\": {\"name\": \"Alice\", \"email\": \"alice@example.com\"}}}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"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\"}}}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"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\"}}}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"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\"}}}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"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\"}}}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""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\""}}}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"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\"}}}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"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\"}}}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"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\"}}}"
}
}'
See REST API for full JSON specification
Example - match a mutation:
import static org.mockserver.model.GraphQLBody.graphQL;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(
graphQL(
"mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name } }",
"CreateUser"
)
)
)
.respond(
response()
.withStatusCode(200)
.withBody("{\"data\": {\"createUser\": {\"id\": \"123\", \"name\": \"Alice\"}}}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"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\"}}}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"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\"}}}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"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\"}}}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"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\"}}}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""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\""}}}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"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\"}}}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"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\"}}}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"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\"}}}"
}
}'
See REST API for full JSON specification
Example - AST subset matching (match any query containing a "users" field):
import static org.mockserver.model.GraphQLBody.graphQL;
import org.mockserver.model.SelectionSetMatchType;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(
graphQL("query { users { id } }")
.withSelectionSetMatchType(SelectionSetMatchType.AST_SUBSET)
.withFields("users")
)
)
.respond(
response()
.withStatusCode(200)
.withBody("{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/graphql"",
""body"": {
""type"": ""GRAPHQL"",
""query"": ""query { users { id } }"",
""selectionSetMatchType"": ""AST_SUBSET"",
""fields"": [""users""]
}
},
""httpResponse"": {
""statusCode"": 200,
""body"": ""{\""data\"": {\""users\"": [{\""id\"": \""1\"", \""name\"": \""Alice\""}]}}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query { users { id } }",
"selectionSetMatchType": "AST_SUBSET",
"fields": ["users"]
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"users\": [{\"id\": \"1\", \"name\": \"Alice\"}]}}"
}
}'
See REST API for full JSON specification
Example - AST exact matching (match a query with exactly these top-level fields):
import static org.mockserver.model.GraphQLBody.graphQL;
import org.mockserver.model.SelectionSetMatchType;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(
graphQL("query GetDashboard { user profile settings }")
.withSelectionSetMatchType(SelectionSetMatchType.AST_EXACT)
)
)
.respond(
response()
.withStatusCode(200)
.withBody("{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/graphql"",
""body"": {
""type"": ""GRAPHQL"",
""query"": ""query GetDashboard { user profile settings }"",
""selectionSetMatchType"": ""AST_EXACT""
}
},
""httpResponse"": {
""statusCode"": 200,
""body"": ""{\""data\"": {\""user\"": {}, \""profile\"": {}, \""settings\"": {}}}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "query GetDashboard { user profile settings }",
"selectionSetMatchType": "AST_EXACT"
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"data\": {\"user\": {}, \"profile\": {}, \"settings\": {}}}"
}
}'
See REST API for full JSON specification
Instead of hand-authoring the response JSON for every GraphQL query, you can register a GraphQL schema on the expectation and let MockServer build a schema-valid response automatically. Provide the schema as either SDL text (e.g. type Query { hello: String }) or an introspection JSON result.
When a request matches an expectation whose GraphQL body carries a schema, MockServer reads the query's selection set and returns a {"data": {...}} response that respects the schema's types:
This is useful for quickly standing up a realistic GraphQL mock from an existing schema — no example payloads required. To return a specific, hand-crafted payload instead, simply provide an httpResponse body as in the matching examples above.
Example - synthesize a response from an SDL schema:
import static org.mockserver.model.GraphQLBody.graphQL;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/graphql")
.withBody(
graphQL("{ user { name email } }")
.withSchema("type Query { user: User } type User { id: ID name: String email: String age: Int }")
)
)
.respond(
response()
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/graphql"",
""body"": {
""type"": ""GRAPHQL"",
""query"": ""{ user { name email } }"",
""schema"": ""type Query { user: User } type User { id: ID name: String email: String age: Int }""
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/graphql",
"body": {
"type": "GRAPHQL",
"query": "{ user { name email } }",
"schema": "type Query { user: User } type User { id: ID name: String email: String age: Int }"
}
}
}'
See REST API for full JSON specification
A request with the query { user { name email } } yields a schema-valid response containing only the requested fields, for example:
{ "data": { "user": { "name": "string", "email": "string" } } }
MockServer supports mocking GraphQL subscriptions over WebSocket using the graphql-transport-ws protocol (also accepts the legacy graphql-ws subprotocol). This allows testing GraphQL subscription clients without a real GraphQL server.
The protocol flow is:
To configure a GraphQL subscription mock, use an httpWebSocketResponse with:
Example - mock a GraphQL subscription that pushes two events:
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpWebSocketResponse.webSocketResponse;
import static org.mockserver.model.WebSocketMessage.webSocketMessage;
import static org.mockserver.model.GraphQLBody.graphQL;
import org.mockserver.model.SelectionSetMatchType;
mockServerClient.when(
request()
.withMethod("GET")
.withPath("/graphql")
).respondWithWebSocket(
webSocketResponse()
.withSubprotocol("graphql-transport-ws")
.withGraphqlSubscriptionFilter(
graphQL("subscription { userUpdated { id name } }")
.withSelectionSetMatchType(SelectionSetMatchType.AST_SUBSET)
)
.withMessage(webSocketMessage("{\"id\": \"1\", \"name\": \"Alice\"}"))
.withMessage(webSocketMessage("{\"id\": \"2\", \"name\": \"Bob\"}"))
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""GET"",
""path"": ""/graphql""
},
""httpWebSocketResponse"": {
""subprotocol"": ""graphql-transport-ws"",
""graphqlSubscriptionFilter"": {
""query"": ""subscription { userUpdated { id name } }"",
""selectionSetMatchType"": ""AST_SUBSET""
},
""messages"": [
{""text"": ""{\""id\"": \""1\"", \""name\"": \""Alice\""}""},
{""text"": ""{\""id\"": \""2\"", \""name\"": \""Bob\""}"", ""delay"": {""timeUnit"": ""MILLISECONDS"", ""value"": 500}}
]
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "GET",
"path": "/graphql"
},
"httpWebSocketResponse": {
"subprotocol": "graphql-transport-ws",
"graphqlSubscriptionFilter": {
"query": "subscription { userUpdated { id name } }",
"selectionSetMatchType": "AST_SUBSET"
},
"messages": [
{"text": "{\"id\": \"1\", \"name\": \"Alice\"}"},
{"text": "{\"id\": \"2\", \"name\": \"Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 500}}
]
}
}'
See REST API for full JSON specification
When a client connects and sends:
{"type": "connection_init"}
// MockServer replies: {"type": "connection_ack"}
{"id": "1", "type": "subscribe", "payload": {"query": "subscription { userUpdated { id name } }"}}
// MockServer replies:
// {"id": "1", "type": "next", "payload": {"data": {"id": "1", "name": "Alice"}}}
// {"id": "1", "type": "next", "payload": {"data": {"id": "2", "name": "Bob"}}}
// {"id": "1", "type": "complete"}
Note: The legacy graphql-ws subprotocol (used by the older subscriptions-transport-ws library) is also accepted. Both use the same message format in MockServer's implementation.
The FUZZY body matcher matches when the request body is similar enough to an expected string, using a deterministic normalised Jaro-Winkler similarity ratio with a configurable threshold. Unlike LLM-based semantic matching, it is fully deterministic — the same inputs always produce the same result and it requires no external service.
Fields:
0.8) — required similarity ratio between 0.0 and 1.0. A value of 1.0 requires an exact match; 0.0 matches anything.false) — when true, both strings are trimmed and lower-cased before comparisonimport static org.mockserver.model.FuzzyBody.fuzzy;
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/api/search")
.withBody(fuzzy("find orders for user", 0.8, false))
)
.respond(
response().withStatusCode(200).withBody("{\"results\": []}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/api/search"",
""body"": {
""type"": ""FUZZY"",
""fuzzy"": ""find orders for user"",
""threshold"": 0.8,
""ignoreCase"": false
}
},
""httpResponse"": {
""statusCode"": 200,
""body"": ""{\""results\"": []}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/api/search",
"body": {
"type": "FUZZY",
"fuzzy": "find orders for user",
"threshold": 0.8,
"ignoreCase": false
}
},
"httpResponse": {
"statusCode": 200,
"body": "{\"results\": []}"
}
}'
See REST API for full JSON specification
A conditionalRequestDefinition lets you combine request matchers with if/then/else logic. If the if guard matches the incoming request, the then branch must also match; otherwise the else branch must match (when absent, the expectation matches whenever the guard is false). Each branch can be any request definition — an httpRequest, an OpenAPI definition, or even a nested conditionalRequestDefinition.
This expectation matches either a JSON POST whose body contains an orderId field, or a GET request. Existing AND-only expectations are unchanged — this construct is entirely opt-in.
import static org.mockserver.model.ConditionalRequestDefinition.requestIf;
new MockServerClient("localhost", 1080)
.when(
requestIf(
request().withMethod("POST").withHeader("content-type", "application/json"),
request().withBody(json("{\"orderId\": \"${json-unit.any-string}\"}")),
request().withMethod("GET")
)
)
.respond(response().withStatusCode(200));
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""conditionalRequestDefinition"": {
""if"": {
""method"": ""POST"",
""headers"": { ""content-type"": [""application/json""] }
},
""then"": {
""body"": {
""type"": ""JSON_SCHEMA"",
""jsonSchema"": ""{\""type\"": \""object\"", \""required\"": [\""orderId\""]}""
}
},
""else"": {
""method"": ""GET""
}
},
""httpResponse"": {
""statusCode"": 200
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"conditionalRequestDefinition": {
"if": {
"method": "POST",
"headers": { "content-type": ["application/json"] }
},
"then": {
"body": {
"type": "JSON_SCHEMA",
"jsonSchema": "{\"type\": \"object\", \"required\": [\"orderId\"]}"
}
},
"else": {
"method": "GET"
}
},
"httpResponse": {
"statusCode": 200
}
}'
See REST API for full JSON specification
A header matcher value may use an opt-in accept:<media-type> directive to match when the request's Accept header finds the media type acceptable per RFC 7231 §5.3.2. This honours q-weights (q=0 excludes a type), type/* and */* wildcards, and specificity/preference ordering.
Use this form as a header value matcher in the Accept header entry:
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("GET")
.withPath("/api/resource")
.withHeader("Accept", "accept:application/json")
)
.respond(
response()
.withStatusCode(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"result\": \"json response\"}")
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""GET"",
""path"": ""/api/resource"",
""headers"": {
""Accept"": [""accept:application/json""]
}
},
""httpResponse"": {
""statusCode"": 200,
""headers"": { ""Content-Type"": [""application/json""] },
""body"": ""{\""result\"": \""json response\""}""
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "GET",
"path": "/api/resource",
"headers": {
"Accept": ["accept:application/json"]
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"result\": \"json response\"}"
}
}'
See REST API for full JSON specification
This expectation matches requests whose Accept header finds application/json acceptable — for example Accept: application/json, Accept: */*, or Accept: application/json;q=0.9, text/html;q=0.5. A request sending Accept: text/html or Accept: application/json;q=0 would not match.
Existing exact/regex header matching is unchanged when the accept: prefix is absent.
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.
Actions can be one of the following types:
If no action is present for a request because no request matcher was matched then:
A response action can be:
either a response literal containing any of the following:
or a templated response using javascript or velocity with a delay
or a callback used to dynamically generate a response based on the request:
as a server side callback implemented as a java class that has a default constructor, implements org.mockserver.mock.action.ExpectationResponseCallback and is available on the classpath
as a client side callback implemented as a closure using the java or javascript clients
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
A forward with fallback action (httpForwardWithFallback) forwards the request to an upstream service, but returns a pre-configured fallback response when the upstream returns an error status code or the connection fails. This is unique to MockServer's hybrid mock+proxy architecture.
Use cases:
import static org.mockserver.model.HttpForwardWithFallback.forwardWithFallback;
import static org.mockserver.model.HttpForward.forward;
import org.mockserver.model.HttpForward;
new MockServerClient("localhost", 1080)
.when(
request()
.withPath("/api/downstream")
)
.forwardWithFallback(
forwardWithFallback()
.withForward(
forward()
.withHost("downstream-service.example.com")
.withPort(443)
.withScheme(HttpForward.Scheme.HTTPS)
)
.withFallback(
response()
.withStatusCode(200)
.withBody("{\"status\": \"cached\", \"data\": []}")
)
.withFallbackOnStatusCodes(500, 502, 503, 504)
.withFallbackOnTimeout(true)
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""path"": ""/api/downstream""
},
""httpForwardWithFallback"": {
""httpForward"": {
""host"": ""downstream-service.example.com"",
""port"": 443,
""scheme"": ""HTTPS""
},
""fallbackResponse"": {
""statusCode"": 200,
""body"": ""{\""status\"": \""cached\"", \""data\"": []}""
},
""fallbackOnStatusCodes"": [500, 502, 503, 504],
""fallbackOnTimeout"": true
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"path": "/api/downstream"
},
"httpForwardWithFallback": {
"httpForward": {
"host": "downstream-service.example.com",
"port": 443,
"scheme": "HTTPS"
},
"fallbackResponse": {
"statusCode": 200,
"body": "{\"status\": \"cached\", \"data\": []}"
},
"fallbackOnStatusCodes": [500, 502, 503, 504],
"fallbackOnTimeout": true
}
}'
See REST API for full JSON specification
An error action can return an invalid response as a sequence of bytes or drop the connection (with an optional delay)
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 have full codec support: ANTHROPIC, OPENAI (Chat Completions), OPENAI_RESPONSES, GEMINI, BEDROCK, AZURE_OPENAI, and OLLAMA — each produces the byte-correct wire format for both single completions and streaming. A request naming an unrecognised provider returns a structured 400 response listing the supported providers.
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);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"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 }
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"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 }
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"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 }
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"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 }
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""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 }
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"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 }
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"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 }
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"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 }
}
}
}'
See REST API for full JSON specification
When streaming is enabled, MockServer expands the completion into provider-correct streaming events with configurable timing physics. Most providers use SSE (Server-Sent Events with text/event-stream) — for example, message_start through message_stop for Anthropic, and chat.completion.chunk deltas for OpenAI. Two providers use alternative wire formats: Ollama uses native NDJSON (newline-delimited JSON with application/x-ndjson), and Bedrock uses the AWS event-stream binary framing (application/vnd.amazon.eventstream) where each streaming chunk is a binary message containing a base64-wrapped JSON payload — matching the InvokeModelWithResponseStream wire format. MockServer emits the correct wire format automatically based on the provider.
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);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/v1/chat/completions""
},
""httpLlmResponse"": {
""provider"": ""OPENAI"",
""model"": ""gpt-4o"",
""completion"": {
""text"": ""Streaming token by token..."",
""streaming"": true,
""streamingPhysics"": {
""timeToFirstToken"": { ""timeUnit"": ""MILLISECONDS"", ""value"": 300 },
""tokensPerSecond"": 50,
""jitter"": 0.2
}
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/v1/chat/completions"
},
"httpLlmResponse": {
"provider": "OPENAI",
"model": "gpt-4o",
"completion": {
"text": "Streaming token by token...",
"streaming": true,
"streamingPhysics": {
"timeToFirstToken": { "timeUnit": "MILLISECONDS", "value": 300 },
"tokensPerSecond": 50,
"jitter": 0.2
}
}
}
}'
See REST API for full JSON specification
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)
.withDeterministicFromInput(true)
)
.applyTo(mockServerClient);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/v1/embeddings""
},
""httpLlmResponse"": {
""provider"": ""OPENAI"",
""embedding"": {
""dimensions"": 1536,
""deterministicFromInput"": true
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/v1/embeddings"
},
"httpLlmResponse": {
"provider": "OPENAI",
"embedding": {
"dimensions": 1536,
"deterministicFromInput": true
}
}
}'
See REST API for full JSON specification
Attach an outputSchema (a JSON Schema) to a completion and MockServer validates the response text against it as the response is encoded. Validation is fail-soft: a mismatch never changes the response body — it adds an x-mockserver-structured-output-invalid response header and logs a warning, so a malformed structured-output fixture is surfaced without breaking the test (a blank or invalid schema, or a missing text, is a no-op). To assert schema conformance over already-recorded traffic instead, use the verify_structured_output tool.
For a stricter check, set enforceOutputSchema to true alongside the schema. This switches MockServer from fail-soft to strict enforcement: when the configured response does not conform to the schema, the mock fails loudly with a provider-correct error (HTTP 502) instead of returning the non-conforming body. This models a real provider's strict response_format: json_schema mode, where the provider guarantees schema-valid output — so a non-conforming strict fixture is treated as a configuration error rather than passed silently. Enforcement is opt-in; the default (unset, or false) keeps the fail-soft validate-and-log behaviour, and it has no effect without an outputSchema.
import static org.mockserver.client.LlmMockBuilder.llmMock;
import static org.mockserver.model.Completion.completion;
import static org.mockserver.model.Provider.ANTHROPIC;
llmMock("/v1/messages")
.withProvider(ANTHROPIC)
.respondingWith(
completion()
.withText("{\"city\":\"Paris\",\"country\":\"France\"}")
.withOutputSchema("{\"type\":\"object\",\"required\":[\"city\",\"country\"]}")
)
.applyTo(mockServerClient);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/v1/messages""
},
""httpLlmResponse"": {
""provider"": ""ANTHROPIC"",
""completion"": {
""text"": ""{\""city\"":\""Paris\"",\""country\"":\""France\""}"",
""outputSchema"": ""{\""type\"":\""object\"",\""required\"":[\""city\"",\""country\""]}""
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "{\"city\":\"Paris\",\"country\":\"France\"}",
"outputSchema": "{\"type\":\"object\",\"required\":[\"city\",\"country\"]}"
}
}
}'
See REST API for full JSON specification
A chaos block on the LLM response injects faults for resilience testing: probabilistic provider errors (e.g. 429/529 with a Retry-After header), mid-stream truncation, malformed SSE, and a stateful request quota. The quota is a deterministic fixed-window rate limit — expectations sharing a quotaName share one counter, so requests past quotaLimit within quotaWindowMillis are rejected with quotaErrorStatus (default 429) and the retryAfter header (the count resets when the window elapses and on server reset). The chaos block is set via the JSON definition (below) or the mock_llm_completion MCP tool, where the full field reference lives.
import static org.mockserver.mock.Expectation.when;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpLlmResponse.llmResponse;
import static org.mockserver.model.LlmChaosProfile.llmChaosProfile;
import static org.mockserver.model.Completion.completion;
import static org.mockserver.model.Provider.ANTHROPIC;
new MockServerClient("localhost", 1080).upsert(
when(
request().withMethod("POST").withPath("/v1/messages")
).thenRespondWithLlm(
llmResponse()
.withProvider(ANTHROPIC)
.withCompletion(
completion().withText("The capital of France is Paris.")
)
.withChaos(
llmChaosProfile()
.withQuotaName("anthropic-account")
.withQuotaLimit(100)
.withQuotaWindowMillis(60000L)
.withQuotaErrorStatus(429)
.withRetryAfter("30")
)
)
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""POST"",
""path"": ""/v1/messages""
},
""httpLlmResponse"": {
""provider"": ""ANTHROPIC"",
""completion"": {
""text"": ""The capital of France is Paris.""
},
""chaos"": {
""quotaName"": ""anthropic-account"",
""quotaLimit"": 100,
""quotaWindowMillis"": 60000,
""quotaErrorStatus"": 429,
""retryAfter"": ""30""
}
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/v1/messages"
},
"httpLlmResponse": {
"provider": "ANTHROPIC",
"completion": {
"text": "The capital of France is Paris."
},
"chaos": {
"quotaName": "anthropic-account",
"quotaLimit": 100,
"quotaWindowMillis": 60000,
"quotaErrorStatus": 429,
"retryAfter": "30"
}
}
}'
See REST API for full JSON specification
For multi-turn LLM conversations with stateful scenario progression, see the multi-turn LLM conversations section of Stateful Scenarios.
A WebSocket response action (httpWebSocketResponse) accepts an HTTP Upgrade request and turns the connection into a WebSocket session. Two modes are available:
Both modes can be combined in a single expectation: MockServer sends any messages immediately after the upgrade, then waits for incoming frames and applies matchers for each one received.
Each entry in the matchers array contains:
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpWebSocketResponse.webSocketResponse;
import static org.mockserver.model.WebSocketMessage.webSocketMessage;
import static org.mockserver.model.WebSocketMessageMatcher.webSocketMessageMatcher;
import org.mockserver.model.WebSocketFrameType;
new MockServerClient("localhost", 1080)
.when(
request().withMethod("GET").withPath("/ws/chat")
)
.respondWithWebSocket(
webSocketResponse()
.withMessage(webSocketMessage("{\"type\": \"connected\"}"))
.withMatcher(
webSocketMessageMatcher()
.withFrameType(WebSocketFrameType.TEXT)
.withText("ping")
.withResponse(webSocketMessage("{\"type\": \"pong\"}"))
)
.withMatcher(
webSocketMessageMatcher()
.withFrameType(WebSocketFrameType.TEXT)
.withText("subscribe")
.withResponse(webSocketMessage("{\"type\": \"ack\"}"))
.withResponse(webSocketMessage("{\"type\": \"data\", \"value\": 42}"))
)
.withCloseConnection(false)
);
var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}).then(
function () {
console.log("expectation created");
},
function (error) {
console.log(error);
}
);
See REST API for full JSON specification
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/expectation",
headers={"Content-Type": "application/json"},
data='''{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/expectation')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/expectation",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""httpRequest"": {
""method"": ""GET"",
""path"": ""/ws/chat""
},
""httpWebSocketResponse"": {
""messages"": [
{""text"": ""{\""type\"": \""connected\""}""}
],
""matchers"": [
{
""frameType"": ""TEXT"",
""textMatcher"": ""ping"",
""responses"": [
{""text"": ""{\""type\"": \""pong\""}""}
]
},
{
""frameType"": ""TEXT"",
""textMatcher"": ""subscribe"",
""responses"": [
{""text"": ""{\""type\"": \""ack\""}""},
{""text"": ""{\""type\"": \""data\"", \""value\"": 42}""}
]
}
],
""closeConnection"": false
}
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/expectation",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}"#;
client.put("http://localhost:1080/mockserver/expectation")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/expectation');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "GET",
"path": "/ws/chat"
},
"httpWebSocketResponse": {
"messages": [
{"text": "{\"type\": \"connected\"}"}
],
"matchers": [
{
"frameType": "TEXT",
"textMatcher": "ping",
"responses": [
{"text": "{\"type\": \"pong\"}"}
]
},
{
"frameType": "TEXT",
"textMatcher": "subscribe",
"responses": [
{"text": "{\"type\": \"ack\"}"},
{"text": "{\"type\": \"data\", \"value\": 42}"}
]
}
],
"closeConnection": false
}
}'
See REST API for full JSON specification
In this example, MockServer sends {"type": "connected"} immediately after the WebSocket upgrade. If the client then sends a frame containing ping, MockServer replies with {"type": "pong"}. A frame containing subscribe triggers a two-message reply sequence. Frames that match no entry are silently ignored.
Bidirectional WebSocket expectations are also authorable in the dashboard Composer — select WebSocket response as the action type and use the Bidirectional frame matchers panel to add entries.
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.
Given a basePath of /api/users, MockServer generates:
| Method | Path | Description | Success Status |
|---|---|---|---|
| GET | /api/users | List all items | 200 |
| POST | /api/users | Create a new item | 201 |
| GET | /api/users/{id} | Get item by ID | 200 |
| PUT | /api/users/{id} | Update item by ID | 200 |
| DELETE | /api/users/{id} | Delete item by ID | 204 |
A CRUD simulation is defined by a JSON object with the following fields:
Register a CRUD simulation using PUT /mockserver/crud:
import org.mockserver.model.CrudExpectationsDefinition;
new MockServerClient("localhost", 1080)
.crud(
new CrudExpectationsDefinition()
.withBasePath("/api/users")
.withIdField("id")
.withIdStrategy(CrudExpectationsDefinition.IdStrategy.AUTO_INCREMENT)
);
// CRUD simulations register at /mockserver/crud (not an expectation)
await fetch("http://localhost:1080/mockserver/crud", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
})
});
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/crud",
headers={"Content-Type": "application/json"},
data='''{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/crud')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/crud",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""basePath"": ""/api/users"",
""idField"": ""id"",
""idStrategy"": ""AUTO_INCREMENT""
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/crud",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}"#;
client.put("http://localhost:1080/mockserver/crud")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/crud');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/crud" -d '{
"basePath": "/api/users",
"idField": "id",
"idStrategy": "AUTO_INCREMENT"
}'
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
import org.mockserver.model.CrudExpectationsDefinition;
new MockServerClient("localhost", 1080)
.crud(
new CrudExpectationsDefinition()
.withBasePath("/api/products")
.withIdStrategy(CrudExpectationsDefinition.IdStrategy.UUID)
);
// CRUD simulations register at /mockserver/crud (not an expectation)
await fetch("http://localhost:1080/mockserver/crud", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"basePath": "/api/products",
"idStrategy": "UUID"
})
});
import requests
# no typed setter — submit the raw expectation JSON over HTTP
requests.put(
"http://localhost:1080/mockserver/crud",
headers={"Content-Type": "application/json"},
data='''{
"basePath": "/api/products",
"idStrategy": "UUID"
}'''
)
require 'net/http'
uri = URI('http://localhost:1080/mockserver/crud')
http = Net::HTTP.new(uri.host, uri.port)
# no typed setter — submit the raw expectation JSON over HTTP
request = Net::HTTP::Put.new(uri, 'Content-Type' => 'application/json')
request.body = <<~'JSON'
{
"basePath": "/api/products",
"idStrategy": "UUID"
}
JSON
http.request(request)
package main
import (
"bytes"
"net/http"
)
func main() {
// no typed setter — submit the raw expectation JSON over HTTP
body := []byte(`{
"basePath": "/api/products",
"idStrategy": "UUID"
}`)
req, _ := http.NewRequest("PUT",
"http://localhost:1080/mockserver/crud",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
using System.Net.Http;
using System.Text;
using var httpClient = new HttpClient();
// no typed setter — submit the raw expectation JSON over HTTP
var json = @"{
""basePath"": ""/api/products"",
""idStrategy"": ""UUID""
}";
await httpClient.PutAsync(
"http://localhost:1080/mockserver/crud",
new StringContent(json, Encoding.UTF8, "application/json")
);
use reqwest::blocking::Client;
let client = Client::new();
// no typed setter — submit the raw expectation JSON over HTTP
let body = r#"{
"basePath": "/api/products",
"idStrategy": "UUID"
}"#;
client.put("http://localhost:1080/mockserver/crud")
.header("Content-Type", "application/json")
.body(body.to_string())
.send()
.unwrap();
$json = <<<'JSON'
{
"basePath": "/api/products",
"idStrategy": "UUID"
}
JSON;
// no typed setter — submit the raw expectation JSON over HTTP
$ch = curl_init('http://localhost:1080/mockserver/crud');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
curl_close($ch);
curl -v -X PUT "http://localhost:1080/mockserver/crud" -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.