description | og_image | hero |
---|---|---|
WireMock extension for gRPC.
|
solutions/grpc/wiremock_grpc_opengraph.png |
solutions/grpc/header.png |
The WireMock extension for gRPC, compatible with WireMock 3.2.0+, supports mocking of gRPC services.
To set up the extension for use, you:
- add the extension JAR dependency to your project.
- create a root directory for WireMock e.g.
src/test/resources/wiremock
with a subdirectory under it, namedgrpc
. - copy the descriptor files generated by
protoc
from your.proto
files into thegrpc
subdirectory.
For details, see Setup below.
At runtime, the extension:
- scans for descriptor files (generated from the service's
.proto
files) in thegrpc
subdirectory of WireMock's root. - using the descriptor file, it converts incoming messages to JSON before passing them to WireMock's core stubbing system, which allows the existing JSON matchers to be used when matching requests.
- converts JSON responses back into proto messages so that all of WireMock's response definition features including templating can be used.
The extension also adds a Java DSL that works with the Java classes generated by protoc
, while also providing a more gRPC idiomatic way of defining stubs.
Add the extension JAR dependency to your project:
Gradle:
implementation 'org.wiremock:wiremock-grpc-extension:{{ versions.grpc_extension_version }}'
Maven:
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-grpc-extension</artifactId>
<version>{{ versions.grpc_extension_version }}</version>
</dependency>
Create a root directory for WireMock, typically src/test/resources/wiremock
, and create a subdirectory in it named grpc
.
Copy the descriptor files generated by protoc
from your .proto
files into the grpc
subdirectory.
Initialise WireMock server with the extension enabled and the root directory set to the path created in the previous steps:
// Same config object also for the JUnit 4 rule or JUnit 5 extension
WireMockServer wm = new WireMockServer(wireMockConfig()
.dynamicPort()
.withRootDirectory("src/test/resources/wiremock")
.extensions(new GrpcExtensionFactory())
));
Initialise a service class for the gRPC service you want to mock (this must be defined in the .proto
file you compiled to a descriptor):
WireMockGrpcService mockGreetingService =
new WireMockGrpcService(
new WireMock(wm.getPort()),
"com.example.grpc.GreetingService"
);
To specify request criteria and response data using JSON:
mockGreetingService.stubFor(
method("greeting")
.withRequestMessage(equalToJson("{ \"name\": \"Tom\" }"))
.willReturn(json("{ "greeting": "Hi Tom from JSON" }")));
Or, with a templated response:
{% raw %}
mockGreetingService.stubFor(
method("greeting")
.withRequestMessage(equalToJson("{ \"name\": \"${json-unit.any-string}\" }"))
.willReturn(
jsonTemplate(
"{ \"greeting\": \"Hello {{jsonPath request.body '$.name'}}\" }")));
{% endraw %}
Matching and stubbing in the Java DSL can also be specified using the Java classes generated by protoc
:
mockGreetingService.stubFor(
method("greeting")
.withRequestMessage(equalToMessage(HelloRequest.newBuilder().setName("Tom")))
.willReturn(message(HelloResponse.newBuilder().setGreeting("OK"))));
You can return gRPC error codes instead of an OK response:
mockGreetingService.stubFor(
method("greeting")
.withRequestMessage(equalToMessage(
HelloRequest.newBuilder().setName("Prereq failure")
))
.willReturn(Status.FAILED_PRECONDITION, "Failed on some prerequisite"));
For a more complete set of examples, see the Java demo project.
Download the standalone JAR at version 3.2.0 or above and the gRPC extension JAR into your working directory.
Create a WireMock data directory with two subdirectories; one for stub mappings, and another for descriptor files:
mkdir -p wiremock wiremock/mappings wiremock/grpc
Compile your proto files into descriptors:
protoc --descriptor_set_out wiremock/grpc/services.dsc ExampleServices.proto
Run WireMock, with both directories you just created on the classpath:
java -cp wiremock-standalone-{{ versions.wiremock_version }}.jar:wiremock-grpc-extension-standalone-{{ versions.grpc_extension_version }}.jar \
wiremock.Run \
--root-dir wiremock
gRPC stubs are defined using WireMock's standard JSON format. Requests should always be matched with a POST
method and a URL path of /<fully-qualified service name>/<method name>
.
{
"request" : {
"urlPath" : "/com.example.grpc.GreetingService/greeting",
"method" : "POST",
"bodyPatterns" : [{
"equalToJson" : "{ \"name\": \"Tom\" }"
}]
},
"response" : {
"status" : 200,
"body" : "{\n \"greeting\": \"Hi Tom\"\n}",
"headers" : {
"grpc-status-name" : "OK"
}
}
}
If you plan to update your gRPC descriptor files at runtime, you can inform WireMock to reload all file descriptors via a POST to the admin API endpoint /__admin/ext/grpc/reset
.
For more see the standalone demo project.