158 lines
4.3 KiB
Markdown
158 lines
4.3 KiB
Markdown
---
|
|
title: "Evans - a CLI gRPC Client"
|
|
date: 2020-08-18
|
|
draft: false
|
|
tags: ["grpc","protobuf","cli"]
|
|
archive: ["Technical Stuff"]
|
|
series: [""]
|
|
featuredImage: "/img/evans/evans.gif"
|
|
---
|
|
# gRPC Server testing, but how?
|
|
|
|
If you develop a REST or GraphQL Api you have various tools available that support you in testing. I personally use [Insomnia](https://insomnia.rest) here, many will also use [Postman](https://www.postman.com/).
|
|
But some people will simply use [cURL](https://curl.haxx.se/). Such tools appear to be less common for gRPC.
|
|
|
|
A tool that I find very useful and that helps me when I work with a gRPC service is [Evans](https://github.com/ktr0731/evans).
|
|
|
|
## Installation & Setup
|
|
|
|
Installation is easiest on MacOS:
|
|
|
|
```bash
|
|
brew tap ktr0731/evans
|
|
brew install evans
|
|
```
|
|
|
|
Binaries for Linux and Windows are also available on [Github](https://github.com/ktr0731/evans).
|
|
|
|
In order to be able to use Evans effectively, I definitely recommend switching on gRPC Reflection. In Go this could look like this:
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/reflection"
|
|
"log"
|
|
"net"
|
|
pb "path/to/your/compiled/protobuf/package"
|
|
)
|
|
|
|
var port = ":50051"
|
|
|
|
func main() {
|
|
lis, err := net.Listen("tcp", port)
|
|
if err != nil {
|
|
log.Fatalf("failed to listen: %v", err)
|
|
}
|
|
|
|
s := grpc.NewServer()
|
|
pb.RegisterExampleserviceServer(s, &exampleService)
|
|
|
|
// Enable reflection:
|
|
reflection.Register(s)
|
|
|
|
if err := s.Serve(lis); err != nil {
|
|
log.Fatalf("failed to serve: %v", err)
|
|
}
|
|
}
|
|
```
|
|
|
|
|
|
## First Steps
|
|
|
|
Evans starts in repl mode with
|
|
```bash
|
|
evans -r -p 50051
|
|
```
|
|
If Reflection enabled as described above, you can display the available services with show package and switch to a service with packache ServiceName.
|
|
|
|

|
|
|
|
## Reflection
|
|
|
|
The whole point, of course, is to test RPCs. Here, too, reflection helps us. If you have chosen a package you can use show Service to display which services are available in the package.
|
|
|
|

|
|
|
|
The nice thing is that you can also see the RPCs including request and response types.
|
|
|
|
To be able to work with the service, it must be selected. service ServiceName selects a service and now you can display the available RPCs with show rpc:
|
|
|
|

|
|
|
|
## Call RPCs
|
|
|
|
With call RPCname you can now call RPCs. In my example here, I am calling Save. Evans now asks interactively the individual fields that are necessary for the call.
|
|

|
|
As you can see, further information is also displayed here. repeate indicates that addresslist is an array and what type the individual fields are. The protobuf file looks like this:
|
|
|
|
```protobuf
|
|
syntax = "proto3";
|
|
|
|
package address;
|
|
|
|
import "helper/helper.proto";
|
|
|
|
option go_package = "models/address";
|
|
|
|
service AddressService {
|
|
rpc GetSingleAddress (address.GetAddressRequest) returns (address.Address) {}
|
|
rpc GetAddressList (address.GetAddressRequest) returns (address.AddressList) {}
|
|
rpc Save (address.AddressList) returns (helper.StatusResponse) {}
|
|
rpc Delete (address.AddressList) returns (helper.StatusResponse) {}
|
|
}
|
|
|
|
message GetAddressRequest {
|
|
string id = 1;
|
|
}
|
|
|
|
message Address {
|
|
string id = 1;
|
|
string firstName = 2;
|
|
string lastName = 3;
|
|
string company = 4;
|
|
string address1 = 5;
|
|
string address2 = 6;
|
|
string zip = 7;
|
|
string city = 8;
|
|
Country country = 9;
|
|
}
|
|
|
|
message AddressList {
|
|
repeated address.Address addresslist = 1;
|
|
}
|
|
|
|
enum Country {
|
|
option allow_alias = true;
|
|
AL = 0 ;
|
|
AD = 1 ;
|
|
AT = 2 ;
|
|
BY = 3 ;
|
|
BE = 4 ;
|
|
...
|
|
ALBANIA = 0 ;
|
|
ANDORRA = 1 ;
|
|
AUSTRIA = 2 ;
|
|
BELARUS = 3 ;
|
|
BELGIUM = 4 ;
|
|
...
|
|
}
|
|
```
|
|
|
|
## Conclusion and alternatives
|
|
|
|
Of course, this can only serve as an overview. Evans can do a lot more, including streaming testing.
|
|
|
|
Personally, I think it makes testing a lot easier. I think it's a good thing that it's a CLI tool, because you don't always have a GUI available.
|
|
|
|
There are of course alternatives. e.g. [Bloom RPC](https://github.com/uw-labs/bloomrpc) is an electron client for gRPC with a nice GUI. Who e.g. is familiar with [GraphiQL](https://github.com/graphql/graphiql) you will quickly find your way around here.
|
|
|
|
[gRPC Curl](https://github.com/fullstorydev/grpcurl) is certainly an option for some.
|
|
|
|
|
|
|
|
|
|
|
|
|