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.

 

How gRPC Mocking Works

When MockServer receives a gRPC request:

  1. The protobuf binary body is decoded to JSON using the loaded proto descriptors
  2. MockServer adds metadata headers to the converted request:
    • x-grpc-service — the fully-qualified gRPC service name
    • x-grpc-method — the RPC method name
    • x-grpc-original-content-type — the original gRPC content type
  3. The converted JSON request is matched against active expectations
  4. The JSON response is encoded back to protobuf binary and returned as a gRPC response

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.

 

Loading Proto Descriptors

MockServer needs proto descriptors to convert between protobuf binary and JSON. There are three ways to load them:

1. Pre-compiled Descriptor Files

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

2. Proto Source Files (Auto-compiled)

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"

3. REST API Upload

Upload compiled descriptors at runtime via the REST API:

curl -v -X PUT "http://localhost:1080/mockserver/grpc/descriptors" \
  --data-binary @service.dsc
 

Docker

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:5.15.0) to pin a known working version.

 

Creating gRPC Expectations

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:

 

Unary RPC

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

Server Streaming RPC

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

Client Streaming RPC

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.

 

Matching gRPC Requests

Since gRPC requests are converted to JSON, all standard MockServer matchers work:

  • Path matching — match on /package.ServiceName/MethodName
  • Header matching — match on x-grpc-service and x-grpc-method headers
  • JSON body matching — match on the JSON-converted protobuf body using exact match, JSON Schema, JsonPath, etc.
  • Regex — use regex matchers on any field
 

gRPC Status Codes

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
0OK
1CANCELLED
2UNKNOWN
3INVALID_ARGUMENT
4DEADLINE_EXCEEDED
5NOT_FOUND
6ALREADY_EXISTS
7PERMISSION_DENIED
8RESOURCE_EXHAUSTED
9FAILED_PRECONDITION
10ABORTED
11OUT_OF_RANGE
12UNIMPLEMENTED
13INTERNAL
14UNAVAILABLE
15DATA_LOSS
16UNAUTHENTICATED
 

Limitations

  • Unary RPC — fully supported
  • Server streaming RPC — fully supported via grpcStreamResponse
  • Client streaming RPC — limited support; stream messages are aggregated into a single request body
  • Bidirectional streaming RPC — not yet supported
 

Configuration

For full details on gRPC configuration properties, see the gRPC Configuration section on the Configuration page.