Reputation: 104
I am trying to test a gRPC service locally.
Here is the sample code
type TestGrpcServer struct {
t *testing.T
Server *grpc.Server
Lis *bufconn.Listener
Conn *grpc.ClientConn
}
func (s *TestGrpcServer) Serve() {
go func() {
if err := s.Server.Serve(s.Lis); err != nil {
s.t.Fail()
}
}()
var err error
s.Conn, err = grpc.DialContext(
context.Background(),
"",
grpc.WithContextDialer(
func(ctx context.Context, str string) (net.Conn, error) {
return s.Lis.Dial()
},
), grpc.WithTransportCredentials(insecure.NewCredentials()),
)
require.NoError(s.t, err)
}
func (s *TestGrpcServer) Stop() {
s.Conn.Close()
s.Server.Stop()
}
func NewTestGrpcServer(t *testing.T) *TestGrpcServer {
buffer := 101024 * 1024
lis := bufconn.Listen(buffer)
s := grpc.NewServer()
return &TestGrpcServer{
t: t,
Server: s,
Lis: lis,
Conn: nil,
}
}
func TestRPC(t *testing.T) {
s := NewTestGrpcServer(t)
// I used mockery to generate this mock
// Let's say this has a function - Create
mockInterface := NewMockInterface(t)
service := NewGrpcService(mockInterface) // This is an implementation of a GRPC service
pb.RegisterGrpcService(s.Server, service) // pb is my proto generated package
s.Serve()
defer s.Stop()
// I am going to intentionally pass a value which will not pass this mock.
mockInterface.On("Create", 13, mock.Anything).Return(modelComputeNode, nil)
client := pb.NewGrpcServiceClient(s.Conn)
ctx := context.Background()
val, err := client.Create(ctx, &CreateMessage{12, "foobar"})
// Deep inside mock, the mock fails with t.FailNow().
// But, the test does not fail immediately. It times out after the configured time instead.
}
I think this is because the server is still "serving", and the defer method on the stop has not yet been called. I expected the defer to be executed after failNow though, but didn't happen (added a debug breakpoint inside the Stop function to verify.
Am I missing something?
Upvotes: 2
Views: 547