mirror of https://github.com/stretchr/testify.git
Merge pull request #1626 from arjun-1/fix-functional-options-diff-indirect-calls
fix: compare functional option names for indirect callspull/1680/head v1.10.0
commit
89cbdd9e7b
58
mock/mock.go
58
mock/mock.go
|
@ -1204,32 +1204,38 @@ type tHelper interface {
|
||||||
func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
|
func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
|
||||||
expectedOpts := reflect.ValueOf(expected)
|
expectedOpts := reflect.ValueOf(expected)
|
||||||
actualOpts := reflect.ValueOf(actual)
|
actualOpts := reflect.ValueOf(actual)
|
||||||
|
|
||||||
|
var expectedFuncs []*runtime.Func
|
||||||
var expectedNames []string
|
var expectedNames []string
|
||||||
for i := 0; i < expectedOpts.Len(); i++ {
|
for i := 0; i < expectedOpts.Len(); i++ {
|
||||||
expectedNames = append(expectedNames, funcName(expectedOpts.Index(i).Interface()))
|
f := runtimeFunc(expectedOpts.Index(i).Interface())
|
||||||
|
expectedFuncs = append(expectedFuncs, f)
|
||||||
|
expectedNames = append(expectedNames, funcName(f))
|
||||||
}
|
}
|
||||||
|
var actualFuncs []*runtime.Func
|
||||||
var actualNames []string
|
var actualNames []string
|
||||||
for i := 0; i < actualOpts.Len(); i++ {
|
for i := 0; i < actualOpts.Len(); i++ {
|
||||||
actualNames = append(actualNames, funcName(actualOpts.Index(i).Interface()))
|
f := runtimeFunc(actualOpts.Index(i).Interface())
|
||||||
|
actualFuncs = append(actualFuncs, f)
|
||||||
|
actualNames = append(actualNames, funcName(f))
|
||||||
}
|
}
|
||||||
if !assert.ObjectsAreEqual(expectedNames, actualNames) {
|
|
||||||
|
if expectedOpts.Len() != actualOpts.Len() {
|
||||||
expectedFmt = fmt.Sprintf("%v", expectedNames)
|
expectedFmt = fmt.Sprintf("%v", expectedNames)
|
||||||
actualFmt = fmt.Sprintf("%v", actualNames)
|
actualFmt = fmt.Sprintf("%v", actualNames)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < expectedOpts.Len(); i++ {
|
for i := 0; i < expectedOpts.Len(); i++ {
|
||||||
expectedOpt := expectedOpts.Index(i).Interface()
|
if !isFuncSame(expectedFuncs[i], actualFuncs[i]) {
|
||||||
actualOpt := actualOpts.Index(i).Interface()
|
expectedFmt = expectedNames[i]
|
||||||
|
actualFmt = actualNames[i]
|
||||||
expectedFunc := expectedNames[i]
|
|
||||||
actualFunc := actualNames[i]
|
|
||||||
if expectedFunc != actualFunc {
|
|
||||||
expectedFmt = expectedFunc
|
|
||||||
actualFmt = actualFunc
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectedOpt := expectedOpts.Index(i).Interface()
|
||||||
|
actualOpt := actualOpts.Index(i).Interface()
|
||||||
|
|
||||||
ot := reflect.TypeOf(expectedOpt)
|
ot := reflect.TypeOf(expectedOpt)
|
||||||
var expectedValues []reflect.Value
|
var expectedValues []reflect.Value
|
||||||
var actualValues []reflect.Value
|
var actualValues []reflect.Value
|
||||||
|
@ -1247,9 +1253,9 @@ func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
|
||||||
reflect.ValueOf(actualOpt).Call(actualValues)
|
reflect.ValueOf(actualOpt).Call(actualValues)
|
||||||
|
|
||||||
for i := 0; i < ot.NumIn(); i++ {
|
for i := 0; i < ot.NumIn(); i++ {
|
||||||
if !assert.ObjectsAreEqual(expectedValues[i].Interface(), actualValues[i].Interface()) {
|
if expectedArg, actualArg := expectedValues[i].Interface(), actualValues[i].Interface(); !assert.ObjectsAreEqual(expectedArg, actualArg) {
|
||||||
expectedFmt = fmt.Sprintf("%s %+v", expectedNames[i], expectedValues[i].Interface())
|
expectedFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], expectedArg, expectedArg)
|
||||||
actualFmt = fmt.Sprintf("%s %+v", expectedNames[i], actualValues[i].Interface())
|
actualFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], actualArg, actualArg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1258,7 +1264,25 @@ func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func funcName(opt interface{}) string {
|
func runtimeFunc(opt interface{}) *runtime.Func {
|
||||||
n := runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name()
|
return runtime.FuncForPC(reflect.ValueOf(opt).Pointer())
|
||||||
return strings.TrimSuffix(path.Base(n), path.Ext(n))
|
}
|
||||||
|
|
||||||
|
func funcName(f *runtime.Func) string {
|
||||||
|
name := f.Name()
|
||||||
|
trimmed := strings.TrimSuffix(path.Base(name), path.Ext(name))
|
||||||
|
splitted := strings.Split(trimmed, ".")
|
||||||
|
|
||||||
|
if len(splitted) == 0 {
|
||||||
|
return trimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
return splitted[len(splitted)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFuncSame(f1, f2 *runtime.Func) bool {
|
||||||
|
f1File, f1Loc := f1.FileLine(f1.Entry())
|
||||||
|
f2File, f2Loc := f2.FileLine(f2.Entry())
|
||||||
|
|
||||||
|
return f1File == f2File && f1Loc == f2Loc
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,22 @@ func OpStr(s string) OptionFn {
|
||||||
o.str = s
|
o.str = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpBytes(b []byte) OptionFn {
|
||||||
|
return func(m *options) {
|
||||||
|
m.str = string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (i *TestExampleImplementation) TheExampleMethodFunctionalOptions(x string, opts ...OptionFn) error {
|
func (i *TestExampleImplementation) TheExampleMethodFunctionalOptions(x string, opts ...OptionFn) error {
|
||||||
args := i.Called(x, opts)
|
args := i.Called(x, opts)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TheExampleMethodFunctionalOptionsIndirect(i *TestExampleImplementation) {
|
||||||
|
i.TheExampleMethodFunctionalOptions("test", OpNum(1), OpStr("foo"))
|
||||||
|
}
|
||||||
|
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
|
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
|
||||||
i.Called(yesorno)
|
i.Called(yesorno)
|
||||||
|
@ -1522,6 +1533,51 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Mock_AssertExpectationsFunctionalOptionsType_Indirectly(t *testing.T) {
|
||||||
|
|
||||||
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpNum(1), OpStr("foo"))).Return(nil).Once()
|
||||||
|
|
||||||
|
tt := new(testing.T)
|
||||||
|
assert.False(t, mockedService.AssertExpectations(tt))
|
||||||
|
|
||||||
|
// make the call now
|
||||||
|
TheExampleMethodFunctionalOptionsIndirect(mockedService)
|
||||||
|
|
||||||
|
// now assert expectations
|
||||||
|
assert.True(t, mockedService.AssertExpectations(tt))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Func(t *testing.T) {
|
||||||
|
|
||||||
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()
|
||||||
|
|
||||||
|
tt := new(testing.T)
|
||||||
|
assert.False(t, mockedService.AssertExpectations(tt))
|
||||||
|
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
mockedService.TheExampleMethodFunctionalOptions("test", OpBytes([]byte("this")))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Arg(t *testing.T) {
|
||||||
|
|
||||||
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()
|
||||||
|
|
||||||
|
tt := new(testing.T)
|
||||||
|
assert.False(t, mockedService.AssertExpectations(tt))
|
||||||
|
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
mockedService.TheExampleMethodFunctionalOptions("test", OpStr("that"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
Loading…
Reference in New Issue