Golang: testing http and grpc servers

Table of Contents

HTTP server

is quite easy to test — here is a nice video about it:


https://youtu.be/hVFEV-ieeew

GRPC server

is a little bit trickier to test.
Here’s an example (it won’t compile, but the main idea is this):

import (
	"context"
	"fmt"
	"log"
	"net"
	"testing"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/test/bufconn"

	desc "path to protobuf generated file"
)

func TestImplementation_GRPCRouting_GetPositionByID_ShouldOK(t *testing.T) {
	var requestedID uint64 = 3
	ctx := context.TODO()
	srv, listener := startGRPCServer(prepareImplementation())
	// it is here to properly stop the server
	defer func() {time.Sleep(10 * time.Millisecond)}()
	defer srv.Stop()
	conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(getBufDialer(listener)), grpc.WithInsecure())
	if err != nil {
		t.Fatalf("failed to dial: %v", err)
	}
	defer conn.Close()
	client := desc.NewVacanciesClient(conn)

	resp, err := client.GetPositionByID(ctx, &desc.PositionByIDRequest{Id: requestedID})

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if resp.GetId() != requestedID {
		t.Fatalf("expected id=%d, got %d", requestedID, resp.GetId())
	}
}

func startGRPCServer(impl *vacancies.Implementation) (*grpc.Server, *bufconn.Listener) {
	bufferSize := 1024 * 1024
	listener := bufconn.Listen(bufferSize)
	srv := grpc.NewServer()
	impl.GetDescription().RegisterGRPC(srv)
	go func() {
		if err := srv.Serve(listener); err != nil {
			log.Fatalf("failed to start grpc server: %v", err)
		}
	}()
	return srv, listener
}

func getBufDialer(listener *bufconn.Listener) func(context.Context, string) (net.Conn, error) {
	return func(ctx context.Context, url string) (net.Conn, error) {
		return listener.Dial()
	}
}

func prepareImplementation(positions ...*models.Position) *vacancies.Implementation {
	if len(positions) == 0 {
		positions = []*models.Position{}

	impl := &vacancies.Implementation{
		PositionStorage: models.NewPositionStorage(positions),
	}

	return impl
}

That code was inspired by this answer — https://stackoverflow.com/a/52080545/801426

LEAVE A COMMENT