Skip to content

Commit

Permalink
displaying mismatch information of arguments diff while panic for clo…
Browse files Browse the repository at this point in the history
…sest function call. closes stretchr#556
  • Loading branch information
Dinesh Kumar committed Feb 11, 2018
1 parent be8372a commit dac0d1e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
26 changes: 15 additions & 11 deletions mock/mock.go
Expand Up @@ -249,14 +249,15 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *
return -1, nil
}

func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
diffCount := 0
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
var diffCount, tempDiffCount int
var closestCall *Call
var errInfo string

for _, call := range m.expectedCalls() {
if call.Method == method {

_, tempDiffCount := call.Arguments.Diff(arguments)
errInfo, tempDiffCount = call.Arguments.Diff(arguments)
if tempDiffCount < diffCount || diffCount == 0 {
diffCount = tempDiffCount
closestCall = call
Expand All @@ -265,11 +266,7 @@ func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *
}
}

if closestCall == nil {
return false, nil
}

return true, closestCall
return closestCall, errInfo
}

func callString(method string, arguments Arguments, includeArgumentValues bool) string {
Expand Down Expand Up @@ -316,6 +313,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
m.mutex.Lock()
//TODO: could combine expected and closes in single loop
found, call := m.findExpectedCall(methodName, arguments...)

if found < 0 {
Expand All @@ -326,11 +324,16 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
// b) the arguments are not what was expected, or
// c) the developer has forgotten to add an accompanying On...Return pair.

closestFound, closestCall := m.findClosestCall(methodName, arguments...)
closestCall, mismatch := m.findClosestCall(methodName, arguments...)
m.mutex.Unlock()

if closestFound {
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(methodName, arguments, true), callString(methodName, closestCall.Arguments, true), diffArguments(closestCall.Arguments, arguments)))
if closestCall != nil {
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
callString(methodName, arguments, true),
callString(methodName, closestCall.Arguments, true),
diffArguments(closestCall.Arguments, arguments),
strings.TrimSpace(mismatch)),
)
} else {
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()))
}
Expand Down Expand Up @@ -604,6 +607,7 @@ func (args Arguments) Is(objects ...interface{}) bool {
//
// Returns the diff string and number of differences found.
func (args Arguments) Diff(objects []interface{}) (string, int) {
//TODO: could return string as error and nil for No difference

var output = "\n"
var differences int
Expand Down
17 changes: 17 additions & 0 deletions mock/mock_test.go
Expand Up @@ -1384,6 +1384,23 @@ func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
}
}

func TestArgumentMatcherToPrintMismatch(t *testing.T) {
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(
`\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool`)
assert.Regexp(t, matchingExp, r)
}
}()

m := new(timer)
m.On("GetTime", MatchedBy(func(i int) bool { return false })).Return("SomeTime").Once()

res := m.GetTime(1)
require.Equal(t, "SomeTime", res)
m.AssertExpectations(t)
}

func ConcurrencyTestMethod(m *Mock) {
m.Called()
}

0 comments on commit dac0d1e

Please sign in to comment.