Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,22 @@ func (c *Call) On(methodName string, arguments ...interface{}) *Call {
return c.Parent.On(methodName, arguments...)
}

// OnF chains a new expectation description onto the mcked interface using
// a function reference instead of a string method name.
// for example:
//
// mock.
// OnF(mocked.MyMethod, 1).Return(nil).
// OnF(mocked.MyOtherMethod, 'a', 'b', 'c').Return(errors.New("Some Error"))
//
// The `method` argument must be a function; otherwise, this call will panic.
// The function name is resolved using reflection and runtime information.
//
//go:noinline
func (c *Call) OnF(method interface{}, args ...interface{}) *Call {
return c.Parent.On(runtimeMethodName(method), args...)
}

// Unset removes all mock handlers that satisfy the call instance arguments from being
// called. Only supported on call instances with static input arguments.
//
Expand Down Expand Up @@ -380,6 +396,18 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
return c
}

// OnF starts a description of an expectation of the specified method
// being called using a function reference instead of a string method name.
//
// Mock.OnF(mocked.MyMethod, arg1, arg2)
//
// The `method` argument must be a function; otherwise, OnF will panic.
// The function name is determined using reflection and runtime information,
// and then passed to On(methodName, args...).
func (m *Mock) OnF(method interface{}, args ...interface{}) *Call {
return m.On(runtimeMethodName(method), args...)
}

// /*
// Recording and responding to activity
// */
Expand Down Expand Up @@ -1303,6 +1331,20 @@ func funcName(f *runtime.Func) string {
return splitted[len(splitted)-1]
}

func runtimeMethodName(f interface{}) string {
t := reflect.TypeOf(f)

if t.Kind() != reflect.Func {
panic("not a function")
}

fname := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()

parts := strings.Split(fname, ".")

return strings.Split(parts[len(parts)-1], "-")[0]
}

func isFuncSame(f1, f2 *runtime.Func) bool {
f1File, f1Loc := f1.FileLine(f1.Entry())
f2File, f2Loc := f2.FileLine(f2.Entry())
Expand Down
11 changes: 11 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,17 @@ func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
})
}

func Test_Mock_OnF(t *testing.T) {
t.Parallel()

// make a test impl object
var mockedService = new(TestExampleImplementation)

c := mockedService.OnF(mockedService.TheExampleMethod)
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
assert.Equal(t, "TheExampleMethod", c.Method)
}

func Test_Mock_Unset(t *testing.T) {
t.Parallel()

Expand Down