gRPC is increasing in popularity. Because of this, there may be a need to mock gRPC based services in early development and testing. This article shows current possibilities, as of mid of 2023.
In general we can divide existing software into two group - free and paid software. Obviously we are interested more in free option, so here we are looking more into that one.
Paid solutions
To keep all options available, it can be mentioned, at least one paid application that provides possibility of gRPC mocking.
Traffic Parrot, as stated on their web pages provides API and service simulation, service virtualization and API mocking software. Evaluation version supports wide range of protocols already, including gRPC.
There is also a possibility to request dedicated support for many others, as stated on their web
As we are interested in gRPC only here are links, that may be helpful:
Resources:
Watching demo may be also a good idea for general overview, how most of mocks (also the free ones) work in general.
Free solutions
As there are free-of-charge solutions in the internet, let’s discuss them briefly, without getting into details too much.
Wiremock
Wiremock is java-based solution, that provides easily configurable stand-alone jar that can serve as a mock. Code repo is here
Wiremock as of now, does not support gRPC natively. It’s planned to be included in the future, but without any hard dates or promises. Still, there is open source solution based on wiremock, called grpc-wiremock, that can be used.
This solution is dedicated to be run with docker. With some effort it’s also possible to run it locally.
Proposed docker file example is provided within repo together with demo proto files and wiremock configuration. There is also .json file for testing with ghz binary available from this source. Setup is quite straightforward.
Example wallet service will be used for a quick demo.
Structure used for testing (with default content):
1 | proto/ |
All mentioned directories are copied into Docker image, as proposed by example Dockerfile.
Docker image is started, and last part should notify about server status, like:
1 | <timestamp> INFO 146 --- [ main] io.adven.grpc.wiremock.HttpMock : WireMock server is started: |
As server supports gRPC reflection, grpcurl can be used to list available services:
1 | $ grpcurl -plaintext 127.0.0.1:50000 list |
Then smoke test for BalanceSerice be done with grpcurl utility
1 | grpcurl \ |
Server should return:
1 | { |
This service was successfully mocked with example provided by mock developer. For a reference same service will be used to test other mocks.
Mountebank
Mountebank is another great tool, that is used for mocking. Code can be found here. In a similar way as wiremock, it doesn’t support gRPC by default, but it’s possible to install plugin, that will make it working.
This can be done via npm:
1 | npm install -g mountebank-grpc-mts |
Then gRPC support should be added into configuration:
1 | cd ${mountebankBaseDir} |
${mountebankBaseDir}
can point to any existing directory of your choice.
After starting server with command
1 | $ mb start --loglevel debug --protofile protocols-grpc.json |
You should be able see information like:
1 | info: [mb:2525] Loaded custom protocol grpc |
The structure in this case is slightly different than for wiremock:
1 | proto |
Content of proto
directory is same as for wiremock and it is located in /tmp/mountebank/grpc/proto
directory. imposters
contains gRPC services definition:
1 | { |
Important thing here is to point server to proto directory, where services and dependencies are defined.
In stubs, there are responses definition in json format. In this case the content is:
1 | { |
To make mock working imposter and stub should be applied to the server.
Imposter import:
1 | $ curl -X POST -d@/tmp/import/grpc.json http://127.0.0.1:2525/imposters |
This is also reported on server side:
1 | info: [mb:2525] POST /imposters |
Similar thing should be done for stub:
1 | $ curl -X POST -d@/tmp/import/wallet.balance.json http://127.0.0.1:2525/imposters/4545/stubs |
Triggered server message looks like:
1 | info: [mb:2525] POST /imposters/4545/stubs |
Now server is expected to be configured. Let’s check same example as for wiremock
1 | grpcurl -plaintext -import-path /tmp/mountebank/grpc/proto -proto wallet.proto -d '{"user_id": 1, "currency": "EUR"}' 127.0.0.1:4545 api.wallet.BalanceService/getUserBalance |
Response is successful, and in debug server messages can be seen how request was processed:
1 | debug: [grpc:4545] sending unary-unary rpc |
In this way it was showed how mountebank can be used to work with gRPC.
Camouflage
Now we can take a look on the only mock server, that offer gRPC support “by default”.
Camouflage is npm-installable application. Code is available in github repo. Again, we re-use protofiles from previous examples to check how mocking can be implemented.
After installing camouflage it should be initiated:
1 | export camouflageBaseDir=/tmp/camouflage |
Structure should be created:
1 | $ ls -1 /tmp/camouflage/ |
It goes with predefined grpc set for protos and mocks. It will be removed and replaced with set related to BalanceService.
1 | rm -rf /tmp/camouflage/grpc/mocks /tmp/camouflage/grpc/protos /tmp/camouflage/.protoignore |
Prepared structure to be used:
1 | /tmp/import/proto |
Proto files are same as previously and in mocks
directory file is created to mimic same replay as seen before:
1 | $ cat /tmp/import/mocks/api/wallet/BalanceService/getUserBalance.mock |
Prepared data should be placed in created structures:
1 | $ cp -a /tmp/import/* /tmp/camouflage/grpc |
Mock configuration should be align to our changes, to enable gRPC.
You need to edit /tmp/camouflage/config.yml
file.
Backup of original file is backed up.
1 | $ cp /tmp/camouflage/config.yml /tmp/camouflage/config.yml.old |
Changes are done:
- loglevel is set to debug
- http.enable is set to false
- grpc.enable is set to true
- name of proto dir is updates from
protos
toproto
Changes can be verified with diff tool:
1 | diff /tmp/camouflage/config.yml /tmp/camouflage/config.yml.old |
Then server is ready and can be started
1 | cd /tmp/camouflage/ |
Following information from server logs is related with gRPC and provided setup:
1 | <timestamp> debug: Found protofile: /tmp/camouflage/grpc/proto/common.proto |
Test is done in a same way as before:
1 | grpcurl -plaintext -import-path /tmp/camouflage/grpc/proto -proto wallet.proto -d '{"user_id": 1, "currency": "EUR"}' 127.0.0.1:4312 api.wallet.BalanceService/getUserBalance |
And reported on server side:
1 | <timestamp> debug: Unary Request: {"user_id":{"low":1,"high":0,"unsigned":true},"currency":"EUR"}. Metadata: {"user-agent":["grpcurl/v1.8.7 grpc-go/1.48.0"]} |
In this time mocking was successful again.
Comparison
Table below shows a brief summary for all discussed mocks.
item | grpc-wiremock | mountebank | camouflage |
---|---|---|---|
code | Java | JavaScript, EJS | TypeScript, JavaScript |
default setup | docker image | npm | npm |
gRPC support type | custom repo | npm plugin | built-in |
gRPC reflection | yes | no | no |