Skip to content

Commit c952903

Browse files
Merge pull request #1786 from brackendawson/1785-mock-argument-stringers
mock: revert to pre-v1.11.0 argument matching behavior for mutating stringers
2 parents f4f5960 + 0cdb408 commit c952903

File tree

2 files changed

+37
-55
lines changed

2 files changed

+37
-55
lines changed

mock/mock.go

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -952,75 +952,56 @@ func (args Arguments) Is(objects ...interface{}) bool {
952952
return true
953953
}
954954

955-
type outputRenderer func() string
956-
957955
// Diff gets a string describing the differences between the arguments
958956
// and the specified objects.
959957
//
960958
// Returns the diff string and number of differences found.
961959
func (args Arguments) Diff(objects []interface{}) (string, int) {
962960
// TODO: could return string as error and nil for No difference
963961

964-
var outputBuilder strings.Builder
962+
output := "\n"
965963
var differences int
966964

967965
maxArgCount := len(args)
968966
if len(objects) > maxArgCount {
969967
maxArgCount = len(objects)
970968
}
971969

972-
outputRenderers := []outputRenderer{}
973-
974970
for i := 0; i < maxArgCount; i++ {
975-
i := i
976971
var actual, expected interface{}
977-
var actualFmt, expectedFmt func() string
972+
var actualFmt, expectedFmt string
978973

979974
if len(objects) <= i {
980975
actual = "(Missing)"
981-
actualFmt = func() string {
982-
return "(Missing)"
983-
}
976+
actualFmt = "(Missing)"
984977
} else {
985978
actual = objects[i]
986-
actualFmt = func() string {
987-
return fmt.Sprintf("(%[1]T=%[1]v)", actual)
988-
}
979+
actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
989980
}
990981

991982
if len(args) <= i {
992983
expected = "(Missing)"
993-
expectedFmt = func() string {
994-
return "(Missing)"
995-
}
984+
expectedFmt = "(Missing)"
996985
} else {
997986
expected = args[i]
998-
expectedFmt = func() string {
999-
return fmt.Sprintf("(%[1]T=%[1]v)", expected)
1000-
}
987+
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
1001988
}
1002989

1003990
if matcher, ok := expected.(argumentMatcher); ok {
1004991
var matches bool
1005992
func() {
1006993
defer func() {
1007994
if r := recover(); r != nil {
1008-
actualFmt = func() string {
1009-
return fmt.Sprintf("panic in argument matcher: %v", r)
1010-
}
995+
actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
1011996
}
1012997
}()
1013998
matches = matcher.Matches(actual)
1014999
}()
10151000
if matches {
1016-
outputRenderers = append(outputRenderers, func() string {
1017-
return fmt.Sprintf("\t%d: PASS: %s matched by %s\n", i, actualFmt(), matcher)
1018-
})
1001+
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
10191002
} else {
10201003
differences++
1021-
outputRenderers = append(outputRenderers, func() string {
1022-
return fmt.Sprintf("\t%d: FAIL: %s not matched by %s\n", i, actualFmt(), matcher)
1023-
})
1004+
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
10241005
}
10251006
} else {
10261007
switch expected := expected.(type) {
@@ -1029,17 +1010,13 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
10291010
if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) {
10301011
// not match
10311012
differences++
1032-
outputRenderers = append(outputRenderers, func() string {
1033-
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, expected, reflect.TypeOf(actual).Name(), actualFmt())
1034-
})
1013+
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
10351014
}
10361015
case *IsTypeArgument:
10371016
actualT := reflect.TypeOf(actual)
10381017
if actualT != expected.t {
10391018
differences++
1040-
outputRenderers = append(outputRenderers, func() string {
1041-
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, safeTypeName(expected.t), actualT, actualFmt())
1042-
})
1019+
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, safeTypeName(expected.t), safeTypeName(actualT), actualFmt)
10431020
}
10441021
case *FunctionalOptionsArgument:
10451022
var name string
@@ -1050,36 +1027,26 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
10501027
const tName = "[]interface{}"
10511028
if name != reflect.TypeOf(actual).String() && len(expected.values) != 0 {
10521029
differences++
1053-
outputRenderers = append(outputRenderers, func() string {
1054-
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, tName, reflect.TypeOf(actual).Name(), actualFmt())
1055-
})
1030+
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt)
10561031
} else {
10571032
if ef, af := assertOpts(expected.values, actual); ef == "" && af == "" {
10581033
// match
1059-
outputRenderers = append(outputRenderers, func() string {
1060-
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, tName, tName)
1061-
})
1034+
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName)
10621035
} else {
10631036
// not match
10641037
differences++
1065-
outputRenderers = append(outputRenderers, func() string {
1066-
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, af, ef)
1067-
})
1038+
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef)
10681039
}
10691040
}
10701041

10711042
default:
10721043
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
10731044
// match
1074-
outputRenderers = append(outputRenderers, func() string {
1075-
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, actualFmt(), expectedFmt())
1076-
})
1045+
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
10771046
} else {
10781047
// not match
10791048
differences++
1080-
outputRenderers = append(outputRenderers, func() string {
1081-
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, actualFmt(), expectedFmt())
1082-
})
1049+
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
10831050
}
10841051
}
10851052
}
@@ -1090,12 +1057,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
10901057
return "No differences.", differences
10911058
}
10921059

1093-
outputBuilder.WriteString("\n")
1094-
for _, r := range outputRenderers {
1095-
outputBuilder.WriteString(r())
1096-
}
1097-
1098-
return outputBuilder.String(), differences
1060+
return output, differences
10991061
}
11001062

11011063
// Assert compares the arguments with the specified objects and fails if

mock/mock_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"regexp"
88
"runtime"
9+
"strconv"
910
"sync"
1011
"testing"
1112
"time"
@@ -2441,3 +2442,22 @@ type user interface {
24412442
type mockUser struct{ Mock }
24422443

24432444
func (m *mockUser) Use(c caller) { m.Called(c) }
2445+
2446+
type mutatingStringer struct {
2447+
N int
2448+
s string
2449+
}
2450+
2451+
func (m *mutatingStringer) String() string {
2452+
m.s = strconv.Itoa(m.N)
2453+
return m.s
2454+
}
2455+
2456+
func TestIssue1785ArgumentWithMutatingStringer(t *testing.T) {
2457+
m := &Mock{}
2458+
m.On("Method", &mutatingStringer{N: 2})
2459+
m.On("Method", &mutatingStringer{N: 1})
2460+
m.MethodCalled("Method", &mutatingStringer{N: 1})
2461+
m.MethodCalled("Method", &mutatingStringer{N: 2})
2462+
m.AssertExpectations(t)
2463+
}

0 commit comments

Comments
 (0)