As discussed in #719, it is currently difficult to unit test streams because there is no way to construct one with a custom/mock implementation of StreamingHandlerConn (or StreamingClientConn for client-side streams). This PR exposes new constructors for the following types:
ServerStream
ServerStreamForClient
ClientStream
ClientStreamForClient
BidiStream
BidiStreamForClient
This allows us to do something along the lines of this (example using mockgen and gomock):
//go:generate $GOBIN/mockgen -destination=stream_mock.go -package=mypackage connectrpc.com/connect StreamingHandlerConn
ctrl := gomock.NewController(t)
mockStreamingHandlerConn := NewMockStreamingHandlerConn(ctrl)
mockStreamingHandlerConn.EXPECT().Send(
// My expected stream message...
).Return(nil)
// New constructor allows us to create a ServerStream using our mock
stream := connect.NewServerStream[controllerv3.Requirements](mockStreamingHandlerConn)
// call service with mock stream
err := myservice.MyRPC(context.Background(), req, stream)
As requested here, I have also updated the internal code to use these new constructors. One thing I wasn't sure about is whether or not we'd want to expose any other parameters. There are a few cases internally where a stream is constructed with additional fields (such as a maybeInitializer) and not being able to pass one into the constructor leads to code like this:
However, my use case doesn't have a need to pass in any other parameters and it keeps the API nice and clean without. I think the style above is fine for internal code. Happy to discuss this if there is a need for it though.
Fixes #719
As discussed in #719, it is currently difficult to unit test streams because there is no way to construct one with a custom/mock implementation of
StreamingHandlerConn
(orStreamingClientConn
for client-side streams). This PR exposes new constructors for the following types:ServerStream
ServerStreamForClient
ClientStream
ClientStreamForClient
BidiStream
BidiStreamForClient
This allows us to do something along the lines of this (example using
mockgen
andgomock
):As requested here, I have also updated the internal code to use these new constructors. One thing I wasn't sure about is whether or not we'd want to expose any other parameters. There are a few cases internally where a stream is constructed with additional fields (such as a
maybeInitializer
) and not being able to pass one into the constructor leads to code like this:However, my use case doesn't have a need to pass in any other parameters and it keeps the API nice and clean without. I think the style above is fine for internal code. Happy to discuss this if there is a need for it though.