diff --git a/gomock/call.go b/gomock/call.go index c5601970..5688184b 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -28,6 +28,7 @@ type Call struct { method string // the name of the method args []Matcher // the args rets []interface{} // the return values (if any) + origin string // file and line number of call setup preReqs []*Call // prerequisite calls @@ -78,8 +79,8 @@ func (c *Call) Do(f interface{}) *Call { func (c *Call) Return(rets ...interface{}) *Call { mt := c.methodType() if len(rets) != mt.NumOut() { - c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d", - c.receiver, c.method, len(rets), mt.NumOut()) + c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]", + c.receiver, c.method, len(rets), mt.NumOut(), c.origin) } for i, ret := range rets { if got, want := reflect.TypeOf(ret), mt.Out(i); got == want { @@ -90,8 +91,8 @@ func (c *Call) Return(rets ...interface{}) *Call { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: // ok default: - c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable", - i, c.receiver, c.method, want) + c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]", + i, c.receiver, c.method, want, c.origin) } } else if got.AssignableTo(want) { // Assignable type relation. Make the assignment now so that the generated code @@ -100,8 +101,8 @@ func (c *Call) Return(rets ...interface{}) *Call { v.Set(reflect.ValueOf(ret)) rets[i] = v.Interface() } else { - c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v", - i, c.receiver, c.method, got, want) + c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]", + i, c.receiver, c.method, got, want, c.origin) } } @@ -124,7 +125,8 @@ func (c *Call) SetArg(n int, value interface{}) *Call { // TODO: This will break on variadic methods. // We will need to check those at invocation time. if n < 0 || n >= mt.NumIn() { - c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn()) + c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]", + n, mt.NumIn(), c.origin) } // Permit setting argument through an interface. // In the interface case, we don't (nay, can't) check the type here. @@ -133,12 +135,14 @@ func (c *Call) SetArg(n int, value interface{}) *Call { case reflect.Ptr: dt := at.Elem() if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) { - c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt) + c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]", + n, vt, dt, c.origin) } case reflect.Interface: // nothing to do default: - c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at) + c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v [%s]", + n, at, c.origin) } c.setArgs[n] = reflect.ValueOf(value) return c @@ -184,7 +188,7 @@ func (c *Call) String() string { args[i] = arg.String() } arguments := strings.Join(args, ", ") - return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments) + return fmt.Sprintf("%T.%v(%s) [%s]", c.receiver, c.method, arguments, c.origin) } // Tests if the given call matches the expected call. diff --git a/gomock/controller.go b/gomock/controller.go index 6ca95280..ed3c3476 100644 --- a/gomock/controller.go +++ b/gomock/controller.go @@ -55,7 +55,11 @@ // - Handle different argument/return types (e.g. ..., chan, map, interface). package gomock -import "sync" +import ( + "fmt" + "runtime" + "sync" +) // A TestReporter is something that can be used to report test failures. // It is satisfied by the standard library's *testing.T. @@ -98,7 +102,8 @@ func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ... ctrl.mu.Lock() defer ctrl.mu.Unlock() - call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, minCalls: 1, maxCalls: 1} + origin := callerInfo(2) + call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, origin: origin, minCalls: 1, maxCalls: 1} ctrl.expectedCalls.Add(call) return call @@ -110,7 +115,8 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf expected := ctrl.expectedCalls.FindMatch(receiver, method, args) if expected == nil { - ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args) + origin := callerInfo(2) + ctrl.t.Fatalf("no matching expected call: %T.%v(%v) [%s]", receiver, method, args, origin) } // Two things happen here: @@ -165,3 +171,10 @@ func (ctrl *Controller) Finish() { ctrl.t.Fatalf("aborting test due to missing call(s)") } } + +func callerInfo(skip int) string { + if _, file, line, ok := runtime.Caller(skip + 1); ok { + return fmt.Sprintf("%s:%d", file, line) + } + return "unknown file" +}