Test gRPC service and client like a pro.
Go >= 1.17
go get github.com/nhatthm/grpcmock
Read more about mocking a gRPC server
Read more about mocking a Unary Method
package main
import (
"context"
"testing"
"time"
"github.com/nhatthm/grpcmock"
grpcAssert "github.com/nhatthm/grpcmock/assert"
"github.com/stretchr/testify/assert"
)
func TestGetItems(t *testing.T) {
t.Parallel()
expected := &Item{Id: 42, Name: "Item 42"}
_, d := grpcmock.MockAndStartServer(
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(),
)
grpcAssert.EqualMessage(t, expected, out)
assert.NoError(t, err)
}
Read more about mocking a Client-Stream Method
package main
import (
"context"
"testing"
"time"
"github.com/nhatthm/grpcmock"
grpcAssert "github.com/nhatthm/grpcmock/assert"
"github.com/stretchr/testify/assert"
)
func TestCreateItems(t *testing.T) {
t.Parallel()
expected := &CreateItemsResponse{NumItems: 1}
_, d := grpcmock.MockAndStartServer(
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(),
)
grpcAssert.EqualMessage(t, expected, out)
assert.NoError(t, err)
}
Read more about mocking a Server-Stream Method
package main
import (
"context"
"testing"
"time"
"github.com/nhatthm/grpcmock"
"github.com/stretchr/testify/assert"
)
func TestListItems(t *testing.T) {
t.Parallel()
expected := []*Item{
{Id: 41, Name: "Item 41"},
{Id: 42, Name: "Item 42"},
}
_, d := grpcmock.MockAndStartServer(
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(&out),
grpcmock.WithContextDialer(d),
grpcmock.WithInsecure(),
)
assert.NoError(t, err)
assert.Len(t, actual, len(expected))
for i := 0; i < len(expected); i++ {
grpcAssert.EqualMessage(t, expected[i], actual[i])
}
}
Coming soon by EOY 2021.
package main
import (
"context"
"time"
"github.com/nhatthm/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
}
package main
import (
"context"
"time"
"github.com/nhatthm/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"
"github.com/nhatthm/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
}
package main
import (
"context"
"time"
"github.com/nhatthm/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"
"github.com/nhatthm/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
}
package main
import (
"context"
"time"
"github.com/nhatthm/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"
"github.com/nhatthm/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
}
If this project help you reduce time to develop, you can give me a cup of coffee :)
or scan this