MockServer supports mocking gRPC services by transparently converting gRPC requests (protobuf over HTTP/2) into JSON-over-HTTP requests internally. This allows the standard expectation matching engine to handle gRPC requests using the same JSON format used for HTTP mocking.
When MockServer receives a gRPC request:
This means you can set up gRPC expectations using the same JSON format and client APIs as HTTP mocking — no special gRPC client tooling is needed.
MockServer needs proto descriptors to convert between protobuf binary and JSON. There are three ways to load them:
Compile your .proto files to descriptor sets and point MockServer at the directory:
protoc --descriptor_set_out=service.dsc --include_imports service.proto
Then configure MockServer:
-Dmockserver.grpcDescriptorDirectory="/path/to/descriptors"
Or via environment variable:
MOCKSERVER_GRPC_DESCRIPTOR_DIRECTORY=/path/to/descriptors
Point MockServer at a directory of .proto source files and they will be compiled at startup using protoc:
-Dmockserver.grpcProtoDirectory="/path/to/protos"
This requires protoc to be available on the system PATH. If protoc is installed elsewhere, configure its path:
-Dmockserver.grpcProtocPath="/usr/local/bin/protoc"
Upload compiled descriptors at runtime via the REST API:
curl -v -X PUT "http://localhost:1080/mockserver/grpc/descriptors" \
--data-binary @service.dsc
When running MockServer in Docker, mount your proto files or descriptors into the container:
docker run -d --rm \
-p 1080:1080 \
-v /local/path/to/protos:/protos \
-e MOCKSERVER_GRPC_PROTO_DIRECTORY=/protos \
mockserver/mockserver:latest
Replace latest with a specific version tag (e.g. mockserver/mockserver:6.1.0) to pin a known working version.
Given a proto file such as:
syntax = "proto3";
package com.example.grpc;
service GreetingService {
rpc Greeting (HelloRequest) returns (HelloResponse);
rpc ListGreetings (HelloRequest) returns (stream HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 1;
}
You can create expectations that match on the JSON-converted request body and the gRPC metadata headers:
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/com.example.grpc.GreetingService/Greeting",
"headers": {
"x-grpc-service": ["com.example.grpc.GreetingService"],
"x-grpc-method": ["Greeting"]
},
"body": {
"type": "JSON",
"json": "{\"name\": \"World\"}"
}
},
"httpResponse": {
"statusCode": 200,
"headers": {
"grpc-status": ["0"]
},
"body": "{\"greeting\": \"Hello World\"}"
}
}'
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/com.example.grpc.GreetingService/Greeting")
.withHeader("x-grpc-service", "com.example.grpc.GreetingService")
.withHeader("x-grpc-method", "Greeting")
.withBody(json("{\"name\": \"World\"}"))
)
.respond(
response()
.withStatusCode(200)
.withHeader("grpc-status", "0")
.withBody("{\"greeting\": \"Hello World\"}")
);
from mockserver import MockServerClient, HttpRequest, HttpResponse, KeyToMultiValue
client = MockServerClient("localhost", 1080)
client.when(
HttpRequest(
method="POST",
path="/com.example.grpc.GreetingService/Greeting",
headers=[
KeyToMultiValue(name="x-grpc-service", values=["com.example.grpc.GreetingService"]),
KeyToMultiValue(name="x-grpc-method", values=["Greeting"])
],
body={"type": "JSON", "json": '{"name": "World"}'}
)
).respond(
HttpResponse(
status_code=200,
headers=[KeyToMultiValue(name="grpc-status", values=["0"])],
body='{"greeting": "Hello World"}'
)
)
require 'mockserver-client'
include MockServer
client = MockServer::Client.new('localhost', 1080)
client.when(
HttpRequest.new(
method: 'POST',
path: '/com.example.grpc.GreetingService/Greeting',
headers: [
{ name: 'x-grpc-service', values: ['com.example.grpc.GreetingService'] },
{ name: 'x-grpc-method', values: ['Greeting'] }
],
body: { type: 'JSON', json: '{"name": "World"}' }
)
).respond(
HttpResponse.new(
status_code: 200,
headers: [{ name: 'grpc-status', values: ['0'] }],
body: '{"greeting": "Hello World"}'
)
)
For server streaming RPCs, use a gRPC stream response to return multiple messages. Each message can have an optional delay:
curl -v -X PUT "http://localhost:1080/mockserver/expectation" -d '{
"httpRequest": {
"method": "POST",
"path": "/com.example.grpc.GreetingService/ListGreetings",
"headers": {
"x-grpc-service": ["com.example.grpc.GreetingService"],
"x-grpc-method": ["ListGreetings"]
}
},
"grpcStreamResponse": {
"statusName": "OK",
"messages": [
{"json": "{\"greeting\": \"Hello Alice\"}"},
{"json": "{\"greeting\": \"Hello Bob\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 100}},
{"json": "{\"greeting\": \"Hello Charlie\"}", "delay": {"timeUnit": "MILLISECONDS", "value": 200}}
]
}
}'
new MockServerClient("localhost", 1080)
.when(
request()
.withMethod("POST")
.withPath("/com.example.grpc.GreetingService/ListGreetings")
.withHeader("x-grpc-service", "com.example.grpc.GreetingService")
.withHeader("x-grpc-method", "ListGreetings")
)
.respondWithGrpcStream(
grpcStreamResponse()
.withStatusName("OK")
.withMessage("{\"greeting\": \"Hello Alice\"}")
.withMessage("{\"greeting\": \"Hello Bob\"}", delay(MILLISECONDS, 100))
.withMessage("{\"greeting\": \"Hello Charlie\"}", delay(MILLISECONDS, 200))
);
from mockserver import MockServerClient, HttpRequest, KeyToMultiValue, GrpcStreamResponse, GrpcStreamMessage, Delay
client = MockServerClient("localhost", 1080)
client.when(
HttpRequest(
method="POST",
path="/com.example.grpc.GreetingService/ListGreetings",
headers=[
KeyToMultiValue(name="x-grpc-service", values=["com.example.grpc.GreetingService"]),
KeyToMultiValue(name="x-grpc-method", values=["ListGreetings"])
]
)
).respond_with_grpc_stream(
GrpcStreamResponse(
status_name="OK",
messages=[
GrpcStreamMessage(json='{"greeting": "Hello Alice"}'),
GrpcStreamMessage(json='{"greeting": "Hello Bob"}', delay=Delay(time_unit="MILLISECONDS", value=100)),
GrpcStreamMessage(json='{"greeting": "Hello Charlie"}', delay=Delay(time_unit="MILLISECONDS", value=200))
]
)
)
require 'mockserver-client'
include MockServer
client = MockServer::Client.new('localhost', 1080)
client.when(
HttpRequest.new(
method: 'POST',
path: '/com.example.grpc.GreetingService/ListGreetings',
headers: [
KeyToMultiValue.new(name: 'x-grpc-service', values: ['com.example.grpc.GreetingService']),
KeyToMultiValue.new(name: 'x-grpc-method', values: ['ListGreetings'])
]
)
).respond_with_grpc_stream(
GrpcStreamResponse.new(
status_name: 'OK',
messages: [
GrpcStreamMessage.new(json: '{"greeting": "Hello Alice"}'),
GrpcStreamMessage.new(json: '{"greeting": "Hello Bob"}', delay: Delay.new(time_unit: 'MILLISECONDS', value: 100)),
GrpcStreamMessage.new(json: '{"greeting": "Hello Charlie"}', delay: Delay.new(time_unit: 'MILLISECONDS', value: 200))
]
)
)
Client streaming requests are converted with the combined stream messages in the request body. MockServer adds an x-grpc-client-streaming header to indicate this is a client streaming request. Client streaming support is limited — see Limitations below.
Since gRPC requests are converted to JSON, all standard MockServer matchers work:
For unary RPCs, set the gRPC status via the grpc-status response header (as shown in the unary example above). For server streaming RPCs, use the statusName field in the grpcStreamResponse action instead. You can also set a grpc-message header (unary) or statusMessage field (streaming) to provide error details. Standard gRPC status codes are supported:
| Code | Name |
|---|---|
| 0 | OK |
| 1 | CANCELLED |
| 2 | UNKNOWN |
| 3 | INVALID_ARGUMENT |
| 4 | DEADLINE_EXCEEDED |
| 5 | NOT_FOUND |
| 6 | ALREADY_EXISTS |
| 7 | PERMISSION_DENIED |
| 8 | RESOURCE_EXHAUSTED |
| 9 | FAILED_PRECONDITION |
| 10 | ABORTED |
| 11 | OUT_OF_RANGE |
| 12 | UNIMPLEMENTED |
| 13 | INTERNAL |
| 14 | UNAVAILABLE |
| 15 | DATA_LOSS |
| 16 | UNAUTHENTICATED |
MockServer can inject gRPC-level faults — UNAVAILABLE, DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED, and other status codes — into matched RPC calls, with optional latency and request-quota controls. Faults are registered per gRPC service name via a dedicated control-plane endpoint and apply before normal request conversion in GrpcToHttpRequestHandler.
This is separate from the health-check serving-status feature described below. See the gRPC Fault Injection section on the Chaos Testing page for the full profile reference and REST API examples.
Kubernetes readiness and liveness probes commonly use the gRPC Health Checking Protocol (grpc.health.v1.Health/Check) to verify that a service is ready to receive traffic. MockServer auto-responds to this well-known method without requiring a proto descriptor — protobuf encoding and decoding is handled manually so health checks work out of the box even when no descriptors have been loaded.
Health checks are enabled by default (grpcHealthCheckEnabled=true). The default serving status for all services is SERVING. You can override the status for individual services or for the global default via a REST endpoint.
| Value | Proto code | Meaning |
|---|---|---|
SERVING |
1 | The service is healthy and ready to accept requests (default) |
NOT_SERVING |
2 | The service is temporarily unavailable (probe will fail) |
UNKNOWN |
0 | Status is unknown |
SERVICE_UNKNOWN |
3 | The named service is not known to this server |
Override the status for a named service:
curl -v -X PUT "http://localhost:1080/mockserver/grpc/health" \
-H "Content-Type: application/json" \
-d '{"service": "my.payments.PaymentService", "status": "NOT_SERVING"}'
Set service to the fully-qualified gRPC service name. Use an empty string ("") to override the default status that applies to all services without an explicit override. The response confirms the registration:
{ "status": "registered", "service": "my.payments.PaymentService", "servingStatus": "NOT_SERVING" }
Read all current status overrides:
curl -v "http://localhost:1080/mockserver/grpc/health"
Returns a JSON object mapping service names to their current status. The empty string key ("_default") shows the global default:
{
"_default": "SERVING",
"my.payments.PaymentService": "NOT_SERVING"
}
All status overrides are cleared on server reset. The GET endpoint returns only services that have had their status explicitly set, plus the global default.
When MockServer receives a request whose path is exactly /grpc.health.v1.Health/Check, the request is intercepted in GrpcToHttpRequestHandler before descriptor lookup — no proto descriptor for the health service is needed. GrpcHealthCheckHandler decodes the 5-byte gRPC frame header and then manually parses the protobuf HealthCheckRequest (field 1 = service name string). It looks up the serving status in GrpcHealthRegistry, which falls back to the default status when no per-service override is registered. The response is a manually-encoded gRPC-framed HealthCheckResponse (field 1 = status enum varint). The whole path bypasses the expectation matching engine so health checks always respond, even with no expectations registered.
MockServer supports the gRPC Server Reflection Protocol out of the box. Tools such as grpcurl and grpcui can use reflection to discover services and describe message types without needing a local .proto file.
Both the v1 and v1alpha reflection service paths are supported:
The reflection service answers from the proto descriptors already loaded into MockServer (via grpcDescriptorDirectory, grpcProtoDirectory, or the REST API upload). No additional configuration is required.
# List all services known to MockServer
grpcurl -plaintext localhost:1080 list
# Describe a specific service
grpcurl -plaintext localhost:1080 describe com.example.grpc.GreetingService
# Describe a message type
grpcurl -plaintext localhost:1080 describe com.example.grpc.HelloRequest
MockServer's gRPC path is buffered-unary: each HTTP/2 request carries exactly one gRPC message. The reflection handler therefore processes a single ServerReflectionRequest per call. This is sufficient for grpcurl list, single symbol lookups, and single file lookups. Fully interactive bidirectional-streaming reflection (a long-lived stream with multiple back-and-forth messages) is not supported by the current pipeline.
MockServer supports gRPC-Web, the variant of gRPC designed for browser clients and environments that cannot use HTTP/2 trailers. gRPC-Web requests are automatically detected and translated to standard gRPC for matching against existing expectations, so no additional configuration or separate expectations are needed.
When MockServer receives a request with a gRPC-Web content type:
gRPC-Web works over both HTTP/1.1 and HTTP/2, making it suitable for browser-based gRPC clients such as grpc-web and Improbable grpc-web.
The built-in gRPC health check (/grpc.health.v1.Health/Check), server reflection, and chaos fault injection all work transparently via gRPC-Web. No special configuration is needed.
The Connect protocol (used by connectrpc) is not currently supported. Connect uses a different framing format (JSON or proto over standard HTTP POST with application/connect+proto content type and trailers in a JSON envelope) that is distinct from gRPC-Web. If you need Connect support, please open a feature request.
For full details on gRPC configuration properties, see the gRPC Configuration section on the Configuration page.