gRPC Serverのテスト
gRPCサーバーは通常はTCPサーバーを立てる必要があり、テストしようとすると面倒です。
そこで、通信部分をin-memoryに差し替えてくれるgrpc/test/bufconnというパッケージを利用すると便利です。
bufconnはネットワークサーバーのように振る舞うListener
を持ち、さらにDial()
メソッドでクライアント接続のように振る舞うnet.Conn
も持つという特徴があります。
bufconnを使ってネットワーク接続なしでテスト
それでは、実際にbufconnを使ったテストを書いてみます。
ソースコードは次のリポジトリにも公開しています。
https://github.com/castaneai/grpc-testing-with-bufconn
たとえばgRPCの公式チュートリアルにもある次のようなシンプルなRPCで考えます。
syntax = "proto3";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
protoc
でGoの定義ファイルを生成して、次のようなディレクトリ構成とします。
$ protoc greeter.proto --go_out=plugins=grpc:.
.
├── go.mod
├── go.sum
├── greeter.pb.go
├── greeter.proto
└── server
├── server.go
└── server_test.go
server/
ディレクトリ以下に2つのファイルを作ります。
-
server.go
サーバーの実装 -
server_test.go
サーバーのテスト(bufconnを使う部分)
server.go
は何も特別なことはなく、通常のgRPCサーバーの実装です。
次に、 server_test.go
ですがここが重要です!
gRPC-Goではgrpc.Dial()
でサーバーへ接続をしますが、そこで grpc.DialContext(grpc.WithCotnextDialer(...))
を使います。
WithContextDialer
の中身をbufconnへの接続 lis.Dial()
に差し替えるというやり方です。
package main
import (
"context"
"log"
"net"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
pb "github.com/castaneai/grpc-testing-with-bufconn"
)
const bufSize = 1024 * 1024
var lis *bufconn.Listener
func init() {
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
go func() {
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}()
}
func bufDialer(ctx context.Context, address string) (net.Conn, error) {
return lis.Dial()
}
func TestSayHello(t *testing.T) {
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
client := pb.NewGreeterClient(conn)
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "test"})
if err != nil {
t.Fatal(err)
}
if resp.GetMessage() != "Hello test" {
t.Fatal("hello reply must be 'Hello test'")
}
}
これでテストを実行してみると、即座にテストが通りました!
$ go test -v ./...
=== RUN TestSayHello
2019/10/04 12:50:04 Received: test
--- PASS: TestSayHello (0.00s)
PASS
ok github.com/castaneai/grpc-testing-with-bufconn/server 0.024s