Evans - a CLI gRPC Client

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 here, many will also use Postman. But some people will simply use cURL. 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.

Installation & Setup

Installation is easiest on MacOS:

1
2
brew tap ktr0731/evans
brew install evans

Binaries for Linux and Windows are also available on Github.

In order to be able to use Evans effectively, I definitely recommend switching on gRPC Reflection. In Go this could look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

1
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.

Start Evans

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.

Service Info

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:

RPCs

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.

Call RPCs
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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 is an electron client for gRPC with a nice GUI. Who e.g. is familiar with GraphiQL you will quickly find your way around here.

gRPC Curl is certainly an option for some.

0%