https://github.com/foxygoat/jig
gRPC mocks with Jsonnet
https://github.com/foxygoat/jig
grpc mock testing
Last synced: 2 months ago
JSON representation
gRPC mocks with Jsonnet
- Host: GitHub
- URL: https://github.com/foxygoat/jig
- Owner: foxygoat
- License: apache-2.0
- Created: 2020-04-10T11:59:39.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2025-03-25T22:07:41.000Z (about 1 year ago)
- Last Synced: 2025-04-21T09:05:16.232Z (11 months ago)
- Topics: grpc, mock, testing
- Language: Go
- Homepage:
- Size: 278 KB
- Stars: 13
- Watchers: 0
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Jig
Jig lets you use [jsonnet] to implement gRPC methods, e.g.:
// Greeter.Hello
function(input) {
response: {
greeting: '💃 : Hello ' + input.request.firstName,
},
}
The jsonnet method definitions can be updated in real time without restarting
jig.
Jig uses protobuf `FileDescriptorSets`, generated by `protoc` into `.pb` files,
as a description of valid gRPC method names, request and response types. Jig
does not need any further pre-generated or pre-compiled code.
[jsonnet]: https://jsonnet.org
## Usage
Generate a FileDescriptorSet for the services to stub with:
protoc --descriptor_set_out service.pb --include_imports service.proto
Put jsonnet method definitions together in a directory, each file named
`...jsonnet`. The jsonnet file is (re-)evaluated when the
gRPC server receives a call to that method.
You can generate skeleton jsonnet method definitions using `jig bones`:
jig bones --proto-set=dir/service.pb --method-dir=dir
Request protobuf messages are marshaled to JSON and passed to the jsonnet method
definition function as the `input` parameter. If the method is a unary,
server-streaming or bidirectional streaming method, the request message is
placed in the `request` field of `input`:
{
request: { ...json-encoded gRPC request protobuf... }
}
If the method is a client-streaming method, the stream of request messages is
placed in the `stream` field of `input` as an array:
{
stream: [ {request1}, {request2}, ...]
}
For bidirectional streaming methods, the jsonnet method definition is evaluated
once for each message on the request stream (with a single message in the
`request` field). Once `EOF` has been received on the request stream, the
jsonnet method definition is evaluated one more time with the `request` field
set to `null`.
Response protobuf messages are unmarshaled from the jsonnet evaluation of the
method definition. The result must evaluate as an object with fields describing
the response to send back to the gRPC client.
If the method is a unary or client-streaming method, the result must have a
`response` field that contains the response message encoded as JSON:
function(input) {
response: { ...json-encoded gRPC response protobuf... }
}
If the method is a server- or bidirectional streaming method, the result must
have a `stream` field that contains an array of response messages encoded as
JSON:
function(input) {
stream: [ {response1}, {response2}, ... ]
}
A [gRPC status] can be returned in the `status` field:
function(input) {
status: {
code: 3,
message: 'Field "foo" failed validation: 0 < foo < 10',
details: [
{
'@type': 'type.googleapis.com/google.protobuf.Duration',
value: '15.2s',
},
],
},
}
If a result has a `status` field, it must not have a `response` or `stream`
field.
The response can reference fields of the input using regular jsonnet references.
See the [testdata samples](./serve/testdata/greet).
The `request` and `response` fields are encoded from/to protobuf messages
according to the [protojson] encoding rules.
To serve these jsonnet methods, run:
jig serve
[gRPC status]: https://www.grpc.io/docs/guides/error/
[protojson]: https://developers.google.com/protocol-buffers/docs/proto3#json
## Playing
### jig serve
Build and start jig on the test data:
. ./bin/activate-hermit
make install
jig serve --http serve/testdata/greet
in a second terminal call it with:
client world
To see streaming, call it with:
client --stream=server world
client --stream=client you me world
client --stream=bidi you me world
The `--http` flag passed to `jig serve` above allows you to make HTTP requests:
curl \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"firstName": "Kitty"}' \
localhost:8080/api/greet/hello
Experiment with the jsonnet method files in the [testdata](./testdata)
directory.
Alternatively there is a traditional, generated gRPC server that the same client
can interact with. Start it with:
server
### jig bones
To get started on writing a jsonnet method definition, the `jig bones`
subcommand generates a skeleton showing the input and output forms of a method.
To see a message with all the different types of message fields:
jig bones --proto-set pb/exemplar/exemplar.pb
To see the structure of the different method streaming types:
jig bones --proto-set pb/greet/greeter.pb
## Development
. ./bin/activate-hermit
make ci
Run `make help` for help on other make targets.