Skip to content

A module providing utilities for testing gRPC servers

License

Notifications You must be signed in to change notification settings

tomasbasham/grpctest

grpctest test

A Go module for testing gRPC servers through in-process integration tests. It provides a test server that communicates over an in-memory buffer rather than network sockets, enabling fast, isolated tests that exercise the complete gRPC stack without requiring port allocation or network configuration.

Motivation

Testing gRPC services typically requires managing network listeners, port allocation, and connection lifecycles. This boilerplate distracts from test logic and introduces flakiness from network-level issues. grpctest eliminates this by providing an in-memory server with a simple API inspired by httptest.

Prerequisites

You will need the following things properly installed on your computer.

Installation

With Go module support (Go 1.11+), simply add the following import

import "github.com/tomasbasham/grpctest"

to your code, and then go [build|run|test] will automatically fetch the necessary dependencies.

Otherwise, to install the grpctest module, run the following command:

go get -u github.com/tomasbasham/grpctest

Philosophy

This module uses bufconn.Listener for in-memory connections rather than real network sockets. This makes tests:

  • Fast: 10-50x faster without kernel and network stack overhead
  • Reliable: No port conflicts or network timing issues
  • Simple: No network resource management

TLS is intentionally omitted. Modern architectures terminate TLS at infrastructure boundaries (load balancers, service meshes), and services communicate over plaintext within the trust boundary. Tests should verify service behaviour, not transport encryption. If you need TLS for specific scenarios (e.g., mutual TLS authentication), configure it via grpc.ServerOption.

The API mirrors grpc.NewServer() for immediate familiarity, and services must be registered before calling Serve() to match standard gRPC usage patterns.

Usage

To use this module, create a test server using the provided constructor, register your gRPC service implementation, and establish client connections through the test server's buffered connection. This approach allows you to test your service handlers against real gRPC transport mechanics whilst maintaining test isolation and performance.

Basic Server Testing

Start by implementing your gRPC service. This example shows a simple echo service:

package server

import (
    "context"

    echopb "github.com/tomasbasham/grpctest/echo/v1"
)

type EchoServer struct {
    echopb.UnimplementedEchoServiceServer
}

func (s *EchoServer) Echo(ctx context.Context, in *echopb.EchoRequest) (*echopb.EchoResponse, error) {
    return &echopb.EchoResponse{Message: in.Message}, nil
}

In your tests, use grpctest.NewServer() to create a test server that starts immediately. The server manages its own buffered connection and exposes a ClientConn() method to create properly configured client connections:

package server_test

import (
    "context"
    "testing"

    "github.com/tomasbasham/echo/internal/server"
    "github.com/tomasbasham/grpctest"

    echopb "github.com/tomasbasham/grpctest/echo/v1"
)

func TestEcho(t *testing.T) {
    s := grpctest.NewServer()
    s.CloseOnCleanup(t)

    // Register Echo service.
    echopb.RegisterEchoServiceServer(s, &server{})
    s.Serve()

    client, err := s.ClientConn()
    if err != nil {
        t.Fatalf("failed to create client: %v", err)
   }

    // The message to echo.
    want := "Hello, world"

    echoClient := echopb.NewEchoServiceClient(client)
    resp, err := echoClient.Echo(context.Background(), &echopb.EchoRequest{Message: want})
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
    if got := resp.Message; got != want {
        t.Errorf("mismatch:\n  got:  %q\n  want: %q", got, want)
    }
}

Advanced Configuration

For scenarios requiring custom server or client options, the testing server can be configured just like a regular gRPC server.

func TestEcho(t *testing.T) {
    // Create server with custom options.
    s := grpctest.NewServer(
        grpc.MaxRecvMsgSize(1024 * 1024 * 10),
    )
    s.CloseOnCleanup(t)

    // Register Echo service before starting.
    echopb.RegisterEchoServiceServer(s, &server.EchoServer{})
    s.Serve()

    conn, err := s.ClientConn()
    if err != nil {
        t.Fatalf("failed to create client: %v", err)
    }

    // Same as above...
}

License

This project is licensed under the MIT License.

About

A module providing utilities for testing gRPC servers

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Contributors 2

  •  
  •  

Languages