mirror of https://github.com/stretchr/testify.git
commit
6905a3e663
50
mock/mock.go
50
mock/mock.go
|
@ -458,6 +458,47 @@ func AnythingOfType(t string) AnythingOfTypeArgument {
|
|||
return AnythingOfTypeArgument(t)
|
||||
}
|
||||
|
||||
// argumentMatcher performs custom argument matching, returning whether or
|
||||
// not the argument is matched by the expectation fixture function.
|
||||
type argumentMatcher struct {
|
||||
// fn is a function which accepts one argument, and returns a bool.
|
||||
fn reflect.Value
|
||||
}
|
||||
|
||||
func (f argumentMatcher) Matches(argument interface{}) bool {
|
||||
expectType := f.fn.Type().In(0)
|
||||
|
||||
if reflect.TypeOf(argument).AssignableTo(expectType) {
|
||||
result := f.fn.Call([]reflect.Value{reflect.ValueOf(argument)})
|
||||
return result[0].Bool()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (f argumentMatcher) String() string {
|
||||
return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name())
|
||||
}
|
||||
|
||||
// Builds an argumentMatcher from |fn|, which must be a function accepting a
|
||||
// single argument (of any type) which returns a bool. If |fn| doesn't match
|
||||
// the required signature, MathedBy() panics.
|
||||
func MatchedBy(fn interface{}) argumentMatcher {
|
||||
fnType := reflect.TypeOf(fn)
|
||||
|
||||
if fnType.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("assert: arguments: %s is not a func", fn))
|
||||
}
|
||||
if fnType.NumIn() != 1 {
|
||||
panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn))
|
||||
}
|
||||
if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool {
|
||||
panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn))
|
||||
}
|
||||
|
||||
return argumentMatcher{fn: reflect.ValueOf(fn)}
|
||||
}
|
||||
|
||||
// Get Returns the argument at the specified index.
|
||||
func (args Arguments) Get(index int) interface{} {
|
||||
if index+1 > len(args) {
|
||||
|
@ -505,7 +546,14 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
expected = args[i]
|
||||
}
|
||||
|
||||
if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||
if matcher, ok := expected.(argumentMatcher); ok {
|
||||
if matcher.Matches(actual) {
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher)
|
||||
} else {
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher)
|
||||
}
|
||||
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||
|
||||
// type checking
|
||||
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
||||
|
|
|
@ -147,6 +147,63 @@ func Test_Mock_On_WithFuncArg(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
|
||||
var mockedService TestExampleImplementation
|
||||
|
||||
mockedService.On("TheExampleMethod",
|
||||
MatchedBy(func(a int) bool {
|
||||
return a == 1
|
||||
}), MatchedBy(func(b int) bool {
|
||||
return b == 2
|
||||
}), MatchedBy(func(c int) bool {
|
||||
return c == 3
|
||||
})).Return(0, nil)
|
||||
|
||||
assert.Panics(t, func() {
|
||||
mockedService.TheExampleMethod(1, 2, 4)
|
||||
})
|
||||
assert.Panics(t, func() {
|
||||
mockedService.TheExampleMethod(2, 2, 3)
|
||||
})
|
||||
assert.NotPanics(t, func() {
|
||||
mockedService.TheExampleMethod(1, 2, 3)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
|
||||
var mockedService TestExampleImplementation
|
||||
|
||||
mockedService.On("TheExampleMethod3",
|
||||
MatchedBy(func(a *ExampleType) bool { return a.ran == true }),
|
||||
).Return(nil)
|
||||
|
||||
mockedService.On("TheExampleMethod3",
|
||||
MatchedBy(func(a *ExampleType) bool { return a.ran == false }),
|
||||
).Return(errors.New("error!"))
|
||||
|
||||
assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil)
|
||||
assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error!")
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
|
||||
var mockedService TestExampleImplementation
|
||||
|
||||
fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2")
|
||||
|
||||
mockedService.On("TheExampleMethodFunc",
|
||||
MatchedBy(func(a func(string) error) bool { return a("string") == fixture1 }),
|
||||
).Return(errors.New("fixture1"))
|
||||
|
||||
mockedService.On("TheExampleMethodFunc",
|
||||
MatchedBy(func(a func(string) error) bool { return a("string") == fixture2 }),
|
||||
).Return(errors.New("fixture2"))
|
||||
|
||||
assert.EqualError(t, mockedService.TheExampleMethodFunc(
|
||||
func(string) error { return fixture1 }), "fixture1")
|
||||
assert.EqualError(t, mockedService.TheExampleMethodFunc(
|
||||
func(string) error { return fixture2 }), "fixture2")
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithVariadicFunc(t *testing.T) {
|
||||
|
||||
// make a test impl object
|
||||
|
@ -937,6 +994,28 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
|
||||
matchFn := func(a int) bool {
|
||||
return a == 123
|
||||
}
|
||||
var args Arguments = []interface{}{"string", MatchedBy(matchFn), true}
|
||||
|
||||
diff, count := args.Diff([]interface{}{"string", 124, true})
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Contains(t, diff, `%!s(int=124) not matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", false, true})
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Contains(t, diff, `%!s(bool=false) not matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", 123, false})
|
||||
assert.Contains(t, diff, `%!s(int=123) matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", 123, true})
|
||||
assert.Equal(t, 0, count)
|
||||
assert.Contains(t, diff, `No differences.`)
|
||||
}
|
||||
|
||||
func Test_Arguments_Assert(t *testing.T) {
|
||||
|
||||
var args Arguments = []interface{}{"string", 123, true}
|
||||
|
|
Loading…
Reference in New Issue