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

Commit 82ce4a7

Browse files
authored
feat validate Do & DoReturn args (#558)
Previous behavior was a panic would happen if the number of args did not match. Now the test should fail more gracefully and allow for better debugging. Fixes: #71
1 parent d19a212 commit 82ce4a7

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

gomock/call.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,14 @@ func (c *Call) DoAndReturn(f interface{}) *Call {
113113
v := reflect.ValueOf(f)
114114

115115
c.addAction(func(args []interface{}) []interface{} {
116+
c.t.Helper()
116117
vArgs := make([]reflect.Value, len(args))
117118
ft := v.Type()
119+
if c.methodType.NumIn() != ft.NumIn() {
120+
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]",
121+
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
122+
return nil
123+
}
118124
for i := 0; i < len(args); i++ {
119125
if args[i] != nil {
120126
vArgs[i] = reflect.ValueOf(args[i])
@@ -142,6 +148,12 @@ func (c *Call) Do(f interface{}) *Call {
142148
v := reflect.ValueOf(f)
143149

144150
c.addAction(func(args []interface{}) []interface{} {
151+
c.t.Helper()
152+
if c.methodType.NumIn() != v.Type().NumIn() {
153+
c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]",
154+
c.receiver, c.method, v.Type().NumIn(), c.methodType.NumIn(), c.origin)
155+
return nil
156+
}
145157
vArgs := make([]reflect.Value, len(args))
146158
ft := v.Type()
147159
for i := 0; i < len(args); i++ {

gomock/call_test.go

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ var testCases []testCase = []testCase{
142142
doFunc: func(x int) {},
143143
callFunc: func(x int, y int) {},
144144
args: []interface{}{0, 1},
145-
expectPanic: true,
145+
expectPanic: false,
146146
}, {
147147
description: "number of args for Do func don't match Call func",
148148
doFunc: func(x int) bool {
@@ -152,7 +152,7 @@ var testCases []testCase = []testCase{
152152
return true
153153
},
154154
args: []interface{}{0, 1},
155-
expectPanic: true,
155+
expectPanic: false,
156156
}, {
157157
description: "arg type for Do func incompatible with Call func",
158158
doFunc: func(x int) {},
@@ -481,6 +481,104 @@ func TestCall_Do(t *testing.T) {
481481
}
482482
}
483483

484+
func TestCall_Do_NumArgValidation(t *testing.T) {
485+
tests := []struct {
486+
name string
487+
methodType reflect.Type
488+
doFn interface{}
489+
args []interface{}
490+
wantErr bool
491+
}{
492+
{
493+
name: "too few",
494+
methodType: reflect.TypeOf(func(one, two string) {}),
495+
doFn: func(one string) {},
496+
args: []interface{}{"too", "few"},
497+
wantErr: true,
498+
},
499+
{
500+
name: "too many",
501+
methodType: reflect.TypeOf(func(one, two string) {}),
502+
doFn: func(one, two, three string) {},
503+
args: []interface{}{"too", "few"},
504+
wantErr: true,
505+
},
506+
{
507+
name: "just right",
508+
methodType: reflect.TypeOf(func(one, two string) {}),
509+
doFn: func(one string, two string) {},
510+
args: []interface{}{"just", "right"},
511+
wantErr: false,
512+
},
513+
}
514+
for _, tt := range tests {
515+
t.Run(tt.name, func(t *testing.T) {
516+
tr := &mockTestReporter{}
517+
call := &Call{
518+
t: tr,
519+
methodType: tt.methodType,
520+
}
521+
call.Do(tt.doFn)
522+
call.actions[0](tt.args)
523+
if tt.wantErr && tr.fatalCalls != 1 {
524+
t.Fatalf("expected call to fail")
525+
}
526+
if !tt.wantErr && tr.fatalCalls != 0 {
527+
t.Fatalf("expected call to pass")
528+
}
529+
})
530+
}
531+
}
532+
533+
func TestCall_DoAndReturn_NumArgValidation(t *testing.T) {
534+
tests := []struct {
535+
name string
536+
methodType reflect.Type
537+
doFn interface{}
538+
args []interface{}
539+
wantErr bool
540+
}{
541+
{
542+
name: "too few",
543+
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
544+
doFn: func(one string) {},
545+
args: []interface{}{"too", "few"},
546+
wantErr: true,
547+
},
548+
{
549+
name: "too many",
550+
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
551+
doFn: func(one, two, three string) string { return "" },
552+
args: []interface{}{"too", "few"},
553+
wantErr: true,
554+
},
555+
{
556+
name: "just right",
557+
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
558+
doFn: func(one string, two string) string { return "" },
559+
args: []interface{}{"just", "right"},
560+
wantErr: false,
561+
},
562+
}
563+
for _, tt := range tests {
564+
t.Run(tt.name, func(t *testing.T) {
565+
tr := &mockTestReporter{}
566+
call := &Call{
567+
t: tr,
568+
methodType: tt.methodType,
569+
}
570+
call.DoAndReturn(tt.doFn)
571+
call.actions[0](tt.args)
572+
if tt.wantErr && tr.fatalCalls != 1 {
573+
t.Fatalf("expected call to fail")
574+
}
575+
if !tt.wantErr && tr.fatalCalls != 0 {
576+
t.Fatalf("expected call to pass")
577+
}
578+
})
579+
}
580+
}
581+
484582
func TestCall_DoAndReturn(t *testing.T) {
485583
for _, tc := range testCases {
486584
t.Run(tc.description, func(t *testing.T) {

0 commit comments

Comments
 (0)