grpcmock icon indicating copy to clipboard operation
grpcmock copied to clipboard

Mock a stream without implying an `io.EOF` return

Open seanlafferty-ibm opened this issue 4 weeks ago • 2 comments

I'm mocking a server with MockServerWithBufConn, and I'm trying to mock a grpc client stream like so

server.ExpectClientStream(myMethodName).Once().Return(myResponse)

however when my app code calls Send() on the stream, it gets back an io.EOF error. Looking through the source code I think this is happening because the underlying bufconn only has one message in the queue, and once there's none left it sends an io.EOF. Im looking for a way to return a nil error instead, as I want to replicate what happens with a real server with a long-lived connection.

Said simply, I looking to to mock a stream response, without also implying the server is terminating the connection.

I tried using Run() instead like

server.ExpectClientStream(myMethodName).Once().Run(func(ctx context.Context, s grpc.ServerStream) (any, error) {
  sends := 1
  for sends <= 2 {
    sends++
    // s.Recv()
    // s.Send()
  }
})

which fixes the app seeing an io.EOF, but ultimately causes other issues since Im only calling Send() once in the application code, not twice.

Does this make sense, or do I have a misunderstanding in how I should be stringing these mocks together?

seanlafferty-ibm avatar Nov 05 '25 19:11 seanlafferty-ibm

Hey I'm away until next Thursday 13th Nov so I can't look into this atm. Could you please tell me what version of grpcmock and grpc you are using? And can you write a small logic for reproducing the issue?

nhatthm avatar Nov 05 '25 22:11 nhatthm

Hey sure, thing. The deps I'm using

	go.nhat.io/grpcmock v0.33.0
	google.golang.org/grpc v1.76.0
	google.golang.org/protobuf v1.36.10
	gotest.tools/v3 v3.5.2

Repro

import (
	"testing"

	"go.nhat.io/grpcmock"
	"go.nhat.io/grpcmock/planner"
	testpb "go.nhat.io/grpcmock/test/grpctest"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"gotest.tools/v3/assert"
)

func TestEOF(t *testing.T) {
	mockServer, mockDialer := grpcmock.MockServerWithBufConn(
		grpcmock.WithPlanner(planner.FirstMatch()),
		grpcmock.RegisterService(testpb.RegisterItemServiceServer),
	)(t)
	conn, err := grpc.NewClient("passthrough:mockURL", grpc.WithContextDialer(mockDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
	t.Cleanup(func() {
		err := conn.Close()
		if err != nil {
			t.Fatal(err)
		}
	})
	assert.NilError(t, err)
	client := testpb.NewItemServiceClient(conn)

	stream, err := client.CreateItems(t.Context())
	assert.NilError(t, err)

	mockServer.ExpectClientStream(testpb.ItemService_CreateItems_FullMethodName).Once().Return(&testpb.CreateItemsResponse{})
	err = stream.Send(&testpb.Item{Id: 52})
	assert.NilError(t, err) // <--- Fails, gets EOF
}

Again, Im not entirely confident I understand how the stream mock is supposed to behave, but my thinking is the mock server shouldn't return an io.EOF (end of stream) until I ask it to 🙂

(In my app, Im trying to write a test that covers a few different scenarios- server closing, server not closing, server erroring, Send()s kicking off at certain intervals, etc)

seanlafferty-ibm avatar Nov 06 '25 00:11 seanlafferty-ibm

@seanlafferty-ibm Hey, I'm back. Could you please tell me your go version, os, and arch? I can't reproduce this on local using the code above.

nhatthm avatar Nov 13 '25 20:11 nhatthm

I have also created https://github.com/nhatthm/grpcmock/pull/169 for testing on several OSes, all passed 🤔

nhatthm avatar Nov 13 '25 21:11 nhatthm

It looks like I can no longer reproduce it either! 😓 I am still using the same pkg versions, and same version of go go version go1.25.4 darwin/amd64. Quite strange, I had that test failing 100% of the time. Maybe some other dep upgrade incidentally fixed it? Sorry! I can report back if I see it again.

seanlafferty-ibm avatar Nov 14 '25 12:11 seanlafferty-ibm

I guess the issue could happen when you use grpcmock <= v0.31.0 with grpc >= v1.75.0. This is the fix https://github.com/nhatthm/grpcmock/pull/158

nhatthm avatar Nov 14 '25 14:11 nhatthm