displaying mismatch information of arguments diff while panic for closest function call. closes #556

devslives-master
Dinesh Kumar 2018-02-11 18:19:20 +05:30
parent be8372ae8e
commit 7538ed3e89
2 changed files with 54 additions and 12 deletions

View File

@ -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
@ -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 {
@ -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 {
@ -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()))
}
@ -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

View File

@ -8,9 +8,10 @@ import (
"testing"
"time"
"runtime"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"runtime"
)
/*
@ -1384,6 +1385,43 @@ 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 TestClosestCallMismatchedArgumentValueInformation(t *testing.T) {
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "1", "999", `0: FAIL: %!s(int=1) != %!s(int=999)`))
assert.Regexp(t, matchingExp, r)
}
}()
m := new(timer)
m.On("GetTime", 999).Return("SomeTime").Once()
_ = m.GetTime(1)
}
func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
rMethod := regexp.QuoteMeta(method)
return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+0: %s\s+The closest call I have is:\s+%s\s+0: %s\s+Diff: %s`,
rMethod, regexp.QuoteMeta(calledArg), rMethod, regexp.QuoteMeta(expectedArg), regexp.QuoteMeta(diff))
}
func ConcurrencyTestMethod(m *Mock) {
m.Called()
}