Skip to content

Commit 9eeaaa7

Browse files
committed
Show file and line number of call during errors
This commit makes erroneous calls show their origin. Unexpected calls show where they happened. Missing calls and improper expectations show where they were set up in the tests. This information is printed after each error message in square brackets. This commit was originally: ooesili@76f75d8 and a PR for it: golang#25. But there were minor conflicts with master from 2 aug 2017: golang@13f3609, which I fixed.
1 parent aaab655 commit 9eeaaa7

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

gomock/call.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Call struct {
2929
methodType reflect.Type // the type of the method
3030
args []Matcher // the args
3131
rets []interface{} // the return values (if any)
32+
origin string // file and line number of call setup
3233

3334
preReqs []*Call // prerequisite calls
3435

@@ -79,8 +80,8 @@ func (c *Call) Do(f interface{}) *Call {
7980
func (c *Call) Return(rets ...interface{}) *Call {
8081
mt := c.methodType
8182
if len(rets) != mt.NumOut() {
82-
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d",
83-
c.receiver, c.method, len(rets), mt.NumOut())
83+
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
84+
c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
8485
}
8586
for i, ret := range rets {
8687
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
@@ -91,8 +92,8 @@ func (c *Call) Return(rets ...interface{}) *Call {
9192
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
9293
// ok
9394
default:
94-
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable",
95-
i, c.receiver, c.method, want)
95+
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
96+
i, c.receiver, c.method, want, c.origin)
9697
}
9798
} else if got.AssignableTo(want) {
9899
// Assignable type relation. Make the assignment now so that the generated code
@@ -101,8 +102,8 @@ func (c *Call) Return(rets ...interface{}) *Call {
101102
v.Set(reflect.ValueOf(ret))
102103
rets[i] = v.Interface()
103104
} else {
104-
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v",
105-
i, c.receiver, c.method, got, want)
105+
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
106+
i, c.receiver, c.method, got, want, c.origin)
106107
}
107108
}
108109

@@ -125,7 +126,8 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
125126
// TODO: This will break on variadic methods.
126127
// We will need to check those at invocation time.
127128
if n < 0 || n >= mt.NumIn() {
128-
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn())
129+
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
130+
n, mt.NumIn(), c.origin)
129131
}
130132
// Permit setting argument through an interface.
131133
// In the interface case, we don't (nay, can't) check the type here.
@@ -134,12 +136,14 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
134136
case reflect.Ptr:
135137
dt := at.Elem()
136138
if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
137-
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt)
139+
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
140+
n, vt, dt, c.origin)
138141
}
139142
case reflect.Interface:
140143
// nothing to do
141144
default:
142-
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at)
145+
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v [%s]",
146+
n, at, c.origin)
143147
}
144148
c.setArgs[n] = reflect.ValueOf(value)
145149
return c
@@ -184,7 +188,7 @@ func (c *Call) String() string {
184188
args[i] = arg.String()
185189
}
186190
arguments := strings.Join(args, ", ")
187-
return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments)
191+
return fmt.Sprintf("%T.%v(%s) [%s]", c.receiver, c.method, arguments, c.origin)
188192
}
189193

190194
// Tests if the given call matches the expected call.

gomock/controller.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ package gomock
5858
import (
5959
"fmt"
6060
"reflect"
61+
"runtime"
6162
"sync"
6263
)
6364

@@ -114,7 +115,8 @@ func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method st
114115
ctrl.mu.Lock()
115116
defer ctrl.mu.Unlock()
116117

117-
call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, minCalls: 1, maxCalls: 1}
118+
origin := callerInfo(2)
119+
call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, origin: origin, minCalls: 1, maxCalls: 1}
118120

119121
ctrl.expectedCalls.Add(call)
120122
return call
@@ -126,7 +128,8 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf
126128

127129
expected := ctrl.expectedCalls.FindMatch(receiver, method, args)
128130
if expected == nil {
129-
ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args)
131+
origin := callerInfo(2)
132+
ctrl.t.Fatalf("no matching expected call: %T.%v(%v) [%s]", receiver, method, args, origin)
130133
}
131134

132135
// Two things happen here:
@@ -181,3 +184,10 @@ func (ctrl *Controller) Finish() {
181184
ctrl.t.Fatalf("aborting test due to missing call(s)")
182185
}
183186
}
187+
188+
func callerInfo(skip int) string {
189+
if _, file, line, ok := runtime.Caller(skip + 1); ok {
190+
return fmt.Sprintf("%s:%d", file, line)
191+
}
192+
return "unknown file"
193+
}

0 commit comments

Comments
 (0)