# README
⚠️ From
v0.20.0
, the project will be rebranded togo.nhat.io/grpcmock
.v0.19.0
is the last version withgithub.com/nhatthm/grpcmock
.
gRPC Test Utilities for Golang
Test gRPC service and client like a pro.
Table of Contents
Prerequisites
Go >= 1.21
Install
go get go.nhat.io/grpcmock
Usage
Mock a gRPC server
Read more about mocking a gRPC server
Unary Method
Read more about mocking a Unary Method
package main
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.nhat.io/grpcmock"
xassert "go.nhat.io/grpcmock/assert"
)
func TestGetItems(t *testing.T) {
t.Parallel()
expected := &Item{Id: 42, Name: "Item 42"}
_, d := grpcmock.MockServerWithBufConn(
grpcmock.RegisterService(RegisterItemServiceServer),
func(s *grpcmock.Server) {
s.ExpectUnary("myservice/GetItem").
WithHeader("locale", "en-US").
WithPayload(&GetItemRequest{Id: 42}).
Return(expected)
},
)(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := &Item{}
err := grpcmock.InvokeUnary(ctx,
"myservice/GetItem",
&GetItemRequest{Id: 42}, out,
grpcmock.WithHeader("locale", "en-US"),
grpcmock.WithContextDialer(d),
grpcmock.WithInsecure(),
)
xassert.EqualMessage(t, expected, out)
assert.NoError(t, err)
}
Client-Stream Method
Read more about mocking a Client-Stream Method
package main
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.nhat.io/grpcmock"
xassert "go.nhat.io/grpcmock/assert"
)
func TestCreateItems(t *testing.T) {
t.Parallel()
expected := &CreateItemsResponse{NumItems: 1}
_, d := grpcmock.MockServerWithBufConn(
grpcmock.RegisterService(RegisterItemServiceServer),
func(s *grpcmock.Server) {
s.ExpectClientStream("myservice/CreateItems").
WithPayload([]*Item{{Id: 42}}).
Return(expected)
},
)(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := &CreateItemsResponse{}
err := grpcmock.InvokeClientStream(ctx, "myservice/CreateItems",
grpcmock.SendAll([]*Item{{Id: 42}}), out,
grpcmock.WithContextDialer(d),
grpcmock.WithInsecure(),
)
xassert.EqualMessage(t, expected, out)
assert.NoError(t, err)
}
Server-Stream Method
Read more about mocking a Server-Stream Method
package main
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.nhat.io/grpcmock"
xassert "go.nhat.io/grpcmock/assert"
)
func TestListItems(t *testing.T) {
t.Parallel()
expected := []*Item{
{Id: 41, Name: "Item 41"},
{Id: 42, Name: "Item 42"},
}
_, d := grpcmock.MockServerWithBufConn(
grpcmock.RegisterService(RegisterItemServiceServer),
func(s *grpcmock.Server) {
s.ExpectServerStream("myservice/ListItems").
WithPayload(&ListItemsRequest{}).
Return(expected)
},
)(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
actual := make([]*Item, 0)
err := grpcmock.InvokeServerStream(ctx,
"myservice/ListItems",
&ListItemsRequest{},
grpcmock.RecvAll(&actual),
grpcmock.WithContextDialer(d),
grpcmock.WithInsecure(),
)
assert.NoError(t, err)
assert.Len(t, actual, len(expected))
for i := 0; i < len(expected); i++ {
xassert.EqualMessage(t, expected[i], actual[i])
}
}
Bidirectional-Stream Method
Read more about mocking a Bidirectional-Stream Method
package main
import (
"context"
"errors"
"fmt"
"io"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.nhat.io/grpcmock"
xassert "go.nhat.io/grpcmock/assert"
"google.golang.org/grpc"
)
func TestTransformItems(t *testing.T) {
t.Parallel()
expected := []*Item{
{Id: 41, Name: "Item 41"},
{Id: 42, Name: "Item 42"},
}
_, d := grpcmock.MockServerWithBufConn(
grpcmock.RegisterService(RegisterItemServiceServer),
func(s *grpcmock.Server) {
s.ExpectBidirectionalStream("myservice/TransformItems").
Run(func(ctx context.Context, s grpc.ServerStream) error {
for {
item := &Item{}
err := s.RecvMsg(item)
if errors.Is(err, io.EOF) {
return nil
}
if err != nil {
return err
}
item.Name = fmt.Sprintf("Modified #%d", item.Id)
if err := s.SendMsg(item); err != nil {
return err
}
}
})
},
)(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
in := []*Item{
{Id: 41, Name: "Item 41"},
{Id: 42, Name: "Item 42"},
}
actual := make([]*Item, 0)
err := grpcmock.InvokeBidirectionalStream(ctx,
"myservice/TransformItems",
grpcmock.SendAndRecvAll(in, &actual),
grpcmock.WithContextDialer(d),
grpcmock.WithInsecure(),
)
assert.NoError(t, err)
assert.Len(t, actual, len(expected))
for i := 0; i < len(expected); i++ {
xassert.EqualMessage(t, expected[i], actual[i])
}
}
Invoke a gRPC method
Unary Method
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc/test/bufconn"
)
func getItem(l *bufconn.Listener, id int32) (*Item, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := &Item{}
err := grpcmock.InvokeUnary(ctx, "myservice/GetItem",
&GetItemRequest{Id: id}, out,
grpcmock.WithHeader("Locale", "en-US"),
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Client-Stream Method
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc/test/bufconn"
)
func createItems(l *bufconn.Listener, items []*Item) (*CreateItemsResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := &CreateItemsResponse{}
err := grpcmock.InvokeClientStream(ctx, "myservice/CreateItems",
grpcmock.SendAll(items), out,
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Or with a custom handler
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
)
func createItems(l *bufconn.Listener, items []*Item) (*CreateItemsResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := &CreateItemsResponse{}
err := grpcmock.InvokeClientStream(ctx, "myservice/CreateItems",
func(s grpc.ClientStream) error {
// Handle the stream here.
return nil
},
out,
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Server-Stream Method
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc/test/bufconn"
)
func listItems(l *bufconn.Listener) ([]*Item, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := make([]*Item, 0)
err := grpcmock.InvokeServerStream(ctx, "myservice/ListItems",
&ListItemsRequest{},
grpcmock.RecvAll(&out),
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Or with a custom handler
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
)
func listItems(l *bufconn.Listener) ([]*Item, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := make([]*Item, 0)
err := grpcmock.InvokeServerStream(ctx, "myservice/ListItems",
&ListItemsRequest{},
func(s grpc.ClientStream) error {
// Handle the stream here.
return nil
},
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Bidirectional-Stream Method
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc/test/bufconn"
)
func transformItems(l *bufconn.Listener, in []*Item) ([]*Item, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := make([]*Item, 0)
err := grpcmock.InvokeBidirectionalStream(ctx, "myservice/TransformItems",
grpcmock.SendAndRecvAll(in, &out),
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Or with a custom handler
package main
import (
"context"
"time"
"go.nhat.io/grpcmock"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
)
func transformItems(l *bufconn.Listener, in []*Item) ([]*Item, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()
out := make([]*Item, 0)
err := grpcmock.InvokeBidirectionalStream(ctx, "myservice/TransformItems",
func(s grpc.ClientStream) error {
// Handle the stream here.
return nil
},
grpcmock.WithBufConnDialer(l),
grpcmock.WithInsecure(),
)
return out, err
}
Donation
If this project help you reduce time to develop, you can give me a cup of coffee :)
Paypal donation
or scan this

# Packages
Package assert provides assertions for grpc.
Package errors provides predefined errors.
Package format formats the requests.
Package invoker constructs a grpc request and executes it.
Package matcher provides custom matchers for gRPC requests.
No description provided by the author
Package must panic on error.
Package planner provides functionalities for deciding what expectation matches the given request.
Package reflect provides a simple reflection on the grpc server.
Package request provides all the expectations for an RPC method.
Package service provides service definition.
Package stream provides functions to send or receive messages using a grpc stream.
Package streamer provides functionalities to work with server-side RPC stream.
Package test provides helpers for testing grpcmock.
Package value provides functionalities to convert a generic value to string.
# Functions
ChainStreamInterceptor is a wrapper of google.golang.org/grpc.ChainStreamInterceptor().
ChainUnaryInterceptor is a wrapper of google.golang.org/grpc.ChainUnaryInterceptor().
ConnectionTimeout is a wrapper of google.golang.org/grpc.ConnectionTimeout().
Creds is a wrapper of google.golang.org/grpc.Creds().
FindServerMethod finds a method in the given server.
InitialConnWindowSize is a wrapper of google.golang.org/grpc.InitialConnWindowSize().
InitialWindowSize is a wrapper of google.golang.org/grpc.InitialWindowSize().
InTapHandle is a wrapper of google.golang.org/grpc.InTapHandle().
InvokeBidirectionalStream invokes a bidirectional-stream method.
InvokeClientStream invokes a client-stream method.
InvokeServerStream invokes a server-stream method.
InvokeUnary invokes a unary method.
KeepaliveEnforcementPolicy is a wrapper of google.golang.org/grpc.KeepaliveEnforcementPolicy().
KeepaliveParams is a wrapper of google.golang.org/grpc.KeepaliveParams().
MatchClientStreamMsgCount matches a number of messages.
MaxConcurrentStreams is a wrapper of google.golang.org/grpc.MaxConcurrentStreams().
MaxHeaderListSize is a wrapper of google.golang.org/grpc.MaxHeaderListSize().
MaxRecvMsgSize is a wrapper of google.golang.org/grpc.MaxRecvMsgSize().
MaxSendMsgSize is a wrapper of google.golang.org/grpc.MaxSendMsgSize().
MockServer starts a new mocked server and ensures all the expectations were met at the end of the test.
MockServerWithBufConn starts a new mocked server with bufconn and ensures all the expectations were met at the end of the test.
MockUnstartedServer mocks the server and ensures all the expectations were met at the end of the test.
NewServer creates mocked server.
NewUnstartedServer returns a new Server but doesn't start it.
NoOpT initiates a new T that does nothing.
ReadBufferSize is a wrapper of google.golang.org/grpc.ReadBufferSize().
RecvAll reads everything from the stream and put into the output.
RegisterService registers a new service using the generated register function.
RegisterServiceFromInstance registers a new service using the generated server interface.
RegisterServiceFromMethods registers a new service using service.Method definition.
SendAll sends everything to the stream.
SendAndRecvAll sends and receives messages to and from grpc server in turn until server sends the io.EOF.
StatsHandler is a wrapper of google.golang.org/grpc.StatsHandler().
StreamInterceptor is a wrapper of google.golang.org/grpc.ChainStreamInterceptor().
UnaryInterceptor is a wrapper of google.golang.org/grpc.ChainUnaryInterceptor().
UnknownServiceHandler is a wrapper of google.golang.org/grpc.UnknownServiceHandler().
WithAddress sets server address.
WithBufConnDialer sets a *bufconn.Listener as the context dialer.
WithCallOptions sets call options.
WithContextDialer sets a context dialer to create connections.
WithDialOptions sets dial options.
WithHeader sets request header.
WithHeaders sets request header.
WithInsecure disables transport security for the connections.
WithListener sets the listener.
WithPlanner sets the expectations' planner.
WithPort sets server address port.
WriteBufferSize is a wrapper of google.golang.org/grpc.WriteBufferSize().
# Interfaces
BidirectionalStreamExpectation represents the expectation for a client-stream request.
ClientStreamExpectation represents the expectation for a client-stream request.
ServerStreamExpectation represents the expectation for a server-stream request.
ServerStreamHandler handles a server-stream request step by step.
T is an interface wrapper around *testing.T.
UnaryExpectation represents the expectation for a unary request.
# Type aliases
ClientStreamHandler handles a client stream.
ContextDialer is to set up the dialer.
InvokeOption sets invoker config.
ServerMocker is a constructor to create a new mocked server.
ServerMockerWithContextDialer starts a new mocked server with a bufconn and returns it as a context dialer for the grpc.DialOption.
ServerOption sets up the mocked server.