mock
mock copied to clipboard
Type-safe return values
Requested feature
This issue proposal generating a typed .Return(
for *gomock.Call
.
it's a re-open for closed issue #427 .
Why the feature is needed
currently .Return(
has a sigurate of func (rets ...interface{})
can accept any return value in compile time.
But wrong return values' type result in always failing at runtime, which can be avoided at compile time.
Proposed solution
User Code
type Auth interface {
// GetByToken return an authorized user by a valid access token.
GetByToken(ctx context.Context, token string) (model.User, error)
}
Generated mocks
// Code generated by MockGen. DO NOT EDIT.
type MockAuthMockRecorder struct {
...
}
// GetByToken indicates an expected call of GetByToken.
func (mr *MockAuthMockRecorder) GetByToken(ctx, token interface{}) *TypedCall {
mr.mock.ctrl.T.Helper()
return &TypedCall{mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByToken",
reflect.TypeOf((*MockAuth)(nil).GetByToken), ctx, token)}
}
type TypedCall struct {
*gomock.Call
}
func (t *TypedCall) Return(typedReturn1 model.User, typedReturn2 error) *gomock.Call {
return t.Call.Return(typedReturn1, typedReturn2)
}
User Test Code
func TestTypeSafeReturn(t *testing.T) {
m := NewMockAuth(gomock.NewController(t))
m.GetByToken(gomock.Any(), gomock.Any()).Return() <== Now we get compile time error
// These should works fine at compile time and runtime.
m.GetByToken(gomock.Any(), gomock.Any()).Return(model.User{}, nil)
m.GetByToken(gomock.Any(), gomock.Any()).Return(model.User{}, errors.New("Not Found"))
}
The reason this suggestion was closed in the path is it sounded like it would be a breaking change. Looking at this prop that is also true. I think if we were going to do something like this in the future we would want to do it in a way that is backwards compatible. Do you have a suggested API that is not a breaking change?
The code will break with this change it already broken at runtime (always panic). This change only make then break early to compile time.
non-breaking-change Suggestions:
- Add a flag in cli that generate new typed call.
- Add a
.TypedReturn(
,.Typed().Return(
or new structNewTypedMockAuth(gomock.NewController(t))
these methods are type-safe.
Personally I prefer first one.
@codyoss any thoughts on these suggestions?
Another mock generator support typed-return
https://github.com/vektra/mockery
And it's kinda funny because it doesn't support type safe matcher...
I don't disagree that overall type-safe returns would be a good idea, but there are potentially people exploiting the current state that may be broken. Let me think about this some more and see if this issue gets more traction. The flag suggestion seems like an okay idea though.
This would also be very interesting for me 👍 . Not having typed returns makes test maintenance harder.