Skip to content
This repository has been archived by the owner on Jun 27, 2023. It is now read-only.

Don't error out for variadic functions in Do/DoReturn #601

Merged
merged 3 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 19 additions & 9 deletions gomock/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,25 @@ func (c *Call) MaxTimes(n int) *Call {
// DoAndReturn declares the action to run when the call is matched.
// The return values from this function are returned by the mocked function.
// It takes an interface{} argument to support n-arity functions.
// The anonymous function must have the same number of input and output arguments as the mocked method.
// The anonymous function must match the function signature mocked method.
func (c *Call) DoAndReturn(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
v := reflect.ValueOf(f)

c.addAction(func(args []interface{}) []interface{} {
c.t.Helper()
vArgs := make([]reflect.Value, len(args))
ft := v.Type()
if c.methodType.NumIn() != ft.NumIn() {
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]",
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
if ft.IsVariadic() {
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.",
c.receiver, c.method)
} else {
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]",
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
}
return nil
}
vArgs := make([]reflect.Value, len(args))
for i := 0; i < len(args); i++ {
if args[i] != nil {
vArgs[i] = reflect.ValueOf(args[i])
Expand All @@ -144,20 +149,25 @@ func (c *Call) DoAndReturn(f interface{}) *Call {
// return values are ignored to retain backward compatibility. To use the
// return values call DoAndReturn.
// It takes an interface{} argument to support n-arity functions.
// The anonymous function must have the same number of input arguments as the mocked method.
// The anonymous function must match the function signature mocked method.
func (c *Call) Do(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
v := reflect.ValueOf(f)

c.addAction(func(args []interface{}) []interface{} {
c.t.Helper()
if c.methodType.NumIn() != v.Type().NumIn() {
c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]",
c.receiver, c.method, v.Type().NumIn(), c.methodType.NumIn(), c.origin)
ft := v.Type()
if c.methodType.NumIn() != ft.NumIn() {
if ft.IsVariadic() {
c.t.Fatalf("wrong number of arguments in Do func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.",
c.receiver, c.method)
} else {
c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]",
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
}
return nil
}
vArgs := make([]reflect.Value, len(args))
ft := v.Type()
for i := 0; i < len(args); i++ {
if args[i] != nil {
vArgs[i] = reflect.ValueOf(args[i])
Expand Down
14 changes: 14 additions & 0 deletions gomock/call_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,13 @@ func TestCall_Do_NumArgValidation(t *testing.T) {
args: []interface{}{"just", "right"},
wantErr: false,
},
{
name: "variadic",
methodType: reflect.TypeOf(func(one, two string) {}),
doFn: func(args ...interface{}) {},
args: []interface{}{"just", "right"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -559,6 +566,13 @@ func TestCall_DoAndReturn_NumArgValidation(t *testing.T) {
args: []interface{}{"just", "right"},
wantErr: false,
},
{
name: "variadic",
methodType: reflect.TypeOf(func(one, two string) {}),
doFn: func(args ...interface{}) string { return "" },
args: []interface{}{"just", "right"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down