-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot test correct handling of serverStream.Send
error
#719
Comments
Hey @edmondop, thanks for raising the issue. Similar discussions have been raised recently in #708 and #694 . Opening the type up for constructors seems like a valuable way to solve this unit style testing. I'd be happy to see an approach but will leave it to others to weigh in on the API. For now you may use an interceptor with a type testStreamConn struct {
connect.StreamingHandlerConn
}
func (c *testStreamConn) Send(msg any) error {
if c.RequestHeader().Get("Fail-Send") != "" {
return errors.New("fail send")
}
return c.StreamingHandlerConn.Send(msg)
} Note: this would still require setting up a httptest server or similar for serving the service. |
Hey @emcfarlane, is there any reason this is more complicated than just adding something like this? func NewServerStream[Res any](conn StreamingHandlerConn) *ServerStream[Res] {
return &ServerStream[Res]{
conn: conn,
}
} We've recently started moving from unary calls to streaming on some of our APIs and mocking them has been a bit of a problem. However, I've got everything working perfectly in this fork with minimal changes. if you're happy with the API, I'm happy to open a PR from my fork. |
@pd93 thanks for having a look. The new constructor methods should be used internally too. |
@emcfarlane Good point, I've updated my fork and opened #731. |
Hey @pd93, the extra API surface may cause issues with maintenance going forwards. For the use cases of mocking another solution could be to create your own interface types which are called from the connect handler methods. Now the stream can be mocked for testing by implementing the interface and calling the indirect implementation. // BidiStream is an interface subset of the methods implemented from [connect.BidiStream]
type BidiStream[Req, Res any] interface {
Send(*Res) error
Receive() (*Req, error)
// other methods required by implementations
}
// PingService.CumSum
// See: https://github.com/connectrpc/connect-go/blob/1abde82b828ae6e6842d09174713defaff0f48de/internal/gen/connect/ping/v1/pingv1connect/ping.connect.go#L180
func (s *Server) CumSum(ctx context.Context, stream *connect.BidiStream[v1.CumSumRequest, v1.CumSumResponse]) error {
return s.cumSum(ctx, stream)
}
func (s *Server) cumSum(ctx context.Context, stream BidiStream[v1.CumSumRequest, v1.CumSumResponse]) error {
return nil // TODO
} Mocking is generally difficult to get right and would usually encourage testing using a connect client to invoke the service. |
Closing the issue until we have a stronger use case for extending the API surface. Workarounds posted in this thread and previous discussions cover the current case. |
Describe the bug
ServerStream.Send()
can return an error, which should be correctly handled in implementation of Handler.Unfortunately, the lack of a public constructor for
ServerStream
doesn't allow to mockStreamingHandlerConn
, and test for the correct behavior of the handler. For example, if the handler needs to do some special cleanup or action whenSend
fails, today it's impossible to unit test thisAdditional context
I'll be happy to contribute back the fix, though it's unclear to me whether we want to make the Handler depends on an interface rather than the
ServerStream
structThe text was updated successfully, but these errors were encountered: