aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/stretchr/testify/mock
diff options
context:
space:
mode:
authoruzhas <uzhas@ydb.tech>2023-11-16 16:04:50 +0300
committeruzhas <uzhas@ydb.tech>2023-11-16 17:46:46 +0300
commit46f0c0079bb50609d2eeb6586642bcf114fc5239 (patch)
tree84e4e4978d57fe5de321ba69bf9d0c290de60a66 /vendor/github.com/stretchr/testify/mock
parent73045e389397816cc2bdd6cd7818b4bce427b265 (diff)
downloadydb-46f0c0079bb50609d2eeb6586642bcf114fc5239.tar.gz
enable ya make for go projects
Diffstat (limited to 'vendor/github.com/stretchr/testify/mock')
-rw-r--r--vendor/github.com/stretchr/testify/mock/doc.go44
-rw-r--r--vendor/github.com/stretchr/testify/mock/gotest/ya.make5
-rw-r--r--vendor/github.com/stretchr/testify/mock/mock.go1226
-rw-r--r--vendor/github.com/stretchr/testify/mock/mock_test.go2141
-rw-r--r--vendor/github.com/stretchr/testify/mock/ya.make19
5 files changed, 3435 insertions, 0 deletions
diff --git a/vendor/github.com/stretchr/testify/mock/doc.go b/vendor/github.com/stretchr/testify/mock/doc.go
new file mode 100644
index 0000000000..d6b3c844cc
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/mock/doc.go
@@ -0,0 +1,44 @@
+// Package mock provides a system by which it is possible to mock your objects
+// and verify calls are happening as expected.
+//
+// # Example Usage
+//
+// The mock package provides an object, Mock, that tracks activity on another object. It is usually
+// embedded into a test object as shown below:
+//
+// type MyTestObject struct {
+// // add a Mock object instance
+// mock.Mock
+//
+// // other fields go here as normal
+// }
+//
+// When implementing the methods of an interface, you wire your functions up
+// to call the Mock.Called(args...) method, and return the appropriate values.
+//
+// For example, to mock a method that saves the name and age of a person and returns
+// the year of their birth or an error, you might write this:
+//
+// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
+// args := o.Called(firstname, lastname, age)
+// return args.Int(0), args.Error(1)
+// }
+//
+// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
+// index position. Given this argument list:
+//
+// (12, true, "Something")
+//
+// You could read them out strongly typed like this:
+//
+// args.Int(0)
+// args.Bool(1)
+// args.String(2)
+//
+// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
+//
+// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
+//
+// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
+// cases you should check for nil first.
+package mock
diff --git a/vendor/github.com/stretchr/testify/mock/gotest/ya.make b/vendor/github.com/stretchr/testify/mock/gotest/ya.make
new file mode 100644
index 0000000000..41f91d0ad8
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/mock/gotest/ya.make
@@ -0,0 +1,5 @@
+GO_TEST_FOR(vendor/github.com/stretchr/testify/mock)
+
+LICENSE(MIT)
+
+END()
diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go
new file mode 100644
index 0000000000..f4b42e44ff
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/mock/mock.go
@@ -0,0 +1,1226 @@
+package mock
+
+import (
+ "errors"
+ "fmt"
+ "path"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+ "github.com/stretchr/objx"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Logf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+ FailNow()
+}
+
+/*
+ Call
+*/
+
+// Call represents a method call and is used for setting expectations,
+// as well as recording activity.
+type Call struct {
+ Parent *Mock
+
+ // The name of the method that was or will be called.
+ Method string
+
+ // Holds the arguments of the method.
+ Arguments Arguments
+
+ // Holds the arguments that should be returned when
+ // this method is called.
+ ReturnArguments Arguments
+
+ // Holds the caller info for the On() call
+ callerInfo []string
+
+ // The number of times to return the return arguments when setting
+ // expectations. 0 means to always return the value.
+ Repeatability int
+
+ // Amount of times this call has been called
+ totalCalls int
+
+ // Call to this method can be optional
+ optional bool
+
+ // Holds a channel that will be used to block the Return until it either
+ // receives a message or is closed. nil means it returns immediately.
+ WaitFor <-chan time.Time
+
+ waitTime time.Duration
+
+ // Holds a handler used to manipulate arguments content that are passed by
+ // reference. It's useful when mocking methods such as unmarshalers or
+ // decoders.
+ RunFn func(Arguments)
+
+ // PanicMsg holds msg to be used to mock panic on the function call
+ // if the PanicMsg is set to a non nil string the function call will panic
+ // irrespective of other settings
+ PanicMsg *string
+
+ // Calls which must be satisfied before this call can be
+ requires []*Call
+}
+
+func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
+ return &Call{
+ Parent: parent,
+ Method: methodName,
+ Arguments: methodArguments,
+ ReturnArguments: make([]interface{}, 0),
+ callerInfo: callerInfo,
+ Repeatability: 0,
+ WaitFor: nil,
+ RunFn: nil,
+ PanicMsg: nil,
+ }
+}
+
+func (c *Call) lock() {
+ c.Parent.mutex.Lock()
+}
+
+func (c *Call) unlock() {
+ c.Parent.mutex.Unlock()
+}
+
+// Return specifies the return arguments for the expectation.
+//
+// Mock.On("DoSomething").Return(errors.New("failed"))
+func (c *Call) Return(returnArguments ...interface{}) *Call {
+ c.lock()
+ defer c.unlock()
+
+ c.ReturnArguments = returnArguments
+
+ return c
+}
+
+// Panic specifies if the functon call should fail and the panic message
+//
+// Mock.On("DoSomething").Panic("test panic")
+func (c *Call) Panic(msg string) *Call {
+ c.lock()
+ defer c.unlock()
+
+ c.PanicMsg = &msg
+
+ return c
+}
+
+// Once indicates that that the mock should only return the value once.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
+func (c *Call) Once() *Call {
+ return c.Times(1)
+}
+
+// Twice indicates that that the mock should only return the value twice.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
+func (c *Call) Twice() *Call {
+ return c.Times(2)
+}
+
+// Times indicates that that the mock should only return the indicated number
+// of times.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
+func (c *Call) Times(i int) *Call {
+ c.lock()
+ defer c.unlock()
+ c.Repeatability = i
+ return c
+}
+
+// WaitUntil sets the channel that will block the mock's return until its closed
+// or a message is received.
+//
+// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
+func (c *Call) WaitUntil(w <-chan time.Time) *Call {
+ c.lock()
+ defer c.unlock()
+ c.WaitFor = w
+ return c
+}
+
+// After sets how long to block until the call returns
+//
+// Mock.On("MyMethod", arg1, arg2).After(time.Second)
+func (c *Call) After(d time.Duration) *Call {
+ c.lock()
+ defer c.unlock()
+ c.waitTime = d
+ return c
+}
+
+// Run sets a handler to be called before returning. It can be used when
+// mocking a method (such as an unmarshaler) that takes a pointer to a struct and
+// sets properties in such struct
+//
+// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) {
+// arg := args.Get(0).(*map[string]interface{})
+// arg["foo"] = "bar"
+// })
+func (c *Call) Run(fn func(args Arguments)) *Call {
+ c.lock()
+ defer c.unlock()
+ c.RunFn = fn
+ return c
+}
+
+// Maybe allows the method call to be optional. Not calling an optional method
+// will not cause an error while asserting expectations
+func (c *Call) Maybe() *Call {
+ c.lock()
+ defer c.unlock()
+ c.optional = true
+ return c
+}
+
+// On chains a new expectation description onto the mocked interface. This
+// allows syntax like.
+//
+// Mock.
+// On("MyMethod", 1).Return(nil).
+// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
+//
+//go:noinline
+func (c *Call) On(methodName string, arguments ...interface{}) *Call {
+ return c.Parent.On(methodName, arguments...)
+}
+
+// Unset removes a mock handler from being called.
+//
+// test.On("func", mock.Anything).Unset()
+func (c *Call) Unset() *Call {
+ var unlockOnce sync.Once
+
+ for _, arg := range c.Arguments {
+ if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
+ panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
+ }
+ }
+
+ c.lock()
+ defer unlockOnce.Do(c.unlock)
+
+ foundMatchingCall := false
+
+ // in-place filter slice for calls to be removed - iterate from 0'th to last skipping unnecessary ones
+ var index int // write index
+ for _, call := range c.Parent.ExpectedCalls {
+ if call.Method == c.Method {
+ _, diffCount := call.Arguments.Diff(c.Arguments)
+ if diffCount == 0 {
+ foundMatchingCall = true
+ // Remove from ExpectedCalls - just skip it
+ continue
+ }
+ }
+ c.Parent.ExpectedCalls[index] = call
+ index++
+ }
+ // trim slice up to last copied index
+ c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index]
+
+ if !foundMatchingCall {
+ unlockOnce.Do(c.unlock)
+ c.Parent.fail("\n\nmock: Could not find expected call\n-----------------------------\n\n%s\n\n",
+ callString(c.Method, c.Arguments, true),
+ )
+ }
+
+ return c
+}
+
+// NotBefore indicates that the mock should only be called after the referenced
+// calls have been called as expected. The referenced calls may be from the
+// same mock instance and/or other mock instances.
+//
+// Mock.On("Do").Return(nil).Notbefore(
+// Mock.On("Init").Return(nil)
+// )
+func (c *Call) NotBefore(calls ...*Call) *Call {
+ c.lock()
+ defer c.unlock()
+
+ for _, call := range calls {
+ if call.Parent == nil {
+ panic("not before calls must be created with Mock.On()")
+ }
+ }
+
+ c.requires = append(c.requires, calls...)
+ return c
+}
+
+// Mock is the workhorse used to track activity on another object.
+// For an example of its usage, refer to the "Example Usage" section at the top
+// of this document.
+type Mock struct {
+ // Represents the calls that are expected of
+ // an object.
+ ExpectedCalls []*Call
+
+ // Holds the calls that were made to this mocked object.
+ Calls []Call
+
+ // test is An optional variable that holds the test struct, to be used when an
+ // invalid mock call was made.
+ test TestingT
+
+ // TestData holds any data that might be useful for testing. Testify ignores
+ // this data completely allowing you to do whatever you like with it.
+ testData objx.Map
+
+ mutex sync.Mutex
+}
+
+// String provides a %v format string for Mock.
+// Note: this is used implicitly by Arguments.Diff if a Mock is passed.
+// It exists because go's default %v formatting traverses the struct
+// without acquiring the mutex, which is detected by go test -race.
+func (m *Mock) String() string {
+ return fmt.Sprintf("%[1]T<%[1]p>", m)
+}
+
+// TestData holds any data that might be useful for testing. Testify ignores
+// this data completely allowing you to do whatever you like with it.
+func (m *Mock) TestData() objx.Map {
+ if m.testData == nil {
+ m.testData = make(objx.Map)
+ }
+
+ return m.testData
+}
+
+/*
+ Setting expectations
+*/
+
+// Test sets the test struct variable of the mock object
+func (m *Mock) Test(t TestingT) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ m.test = t
+}
+
+// fail fails the current test with the given formatted format and args.
+// In case that a test was defined, it uses the test APIs for failing a test,
+// otherwise it uses panic.
+func (m *Mock) fail(format string, args ...interface{}) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ if m.test == nil {
+ panic(fmt.Sprintf(format, args...))
+ }
+ m.test.Errorf(format, args...)
+ m.test.FailNow()
+}
+
+// On starts a description of an expectation of the specified method
+// being called.
+//
+// Mock.On("MyMethod", arg1, arg2)
+func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
+ for _, arg := range arguments {
+ if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
+ panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
+ }
+ }
+
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ c := newCall(m, methodName, assert.CallerInfo(), arguments...)
+ m.ExpectedCalls = append(m.ExpectedCalls, c)
+ return c
+}
+
+// /*
+// Recording and responding to activity
+// */
+
+func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
+ var expectedCall *Call
+
+ for i, call := range m.ExpectedCalls {
+ if call.Method == method {
+ _, diffCount := call.Arguments.Diff(arguments)
+ if diffCount == 0 {
+ expectedCall = call
+ if call.Repeatability > -1 {
+ return i, call
+ }
+ }
+ }
+ }
+
+ return -1, expectedCall
+}
+
+type matchCandidate struct {
+ call *Call
+ mismatch string
+ diffCount int
+}
+
+func (c matchCandidate) isBetterMatchThan(other matchCandidate) bool {
+ if c.call == nil {
+ return false
+ }
+ if other.call == nil {
+ return true
+ }
+
+ if c.diffCount > other.diffCount {
+ return false
+ }
+ if c.diffCount < other.diffCount {
+ return true
+ }
+
+ if c.call.Repeatability > 0 && other.call.Repeatability <= 0 {
+ return true
+ }
+ return false
+}
+
+func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
+ var bestMatch matchCandidate
+
+ for _, call := range m.expectedCalls() {
+ if call.Method == method {
+
+ errInfo, tempDiffCount := call.Arguments.Diff(arguments)
+ tempCandidate := matchCandidate{
+ call: call,
+ mismatch: errInfo,
+ diffCount: tempDiffCount,
+ }
+ if tempCandidate.isBetterMatchThan(bestMatch) {
+ bestMatch = tempCandidate
+ }
+ }
+ }
+
+ return bestMatch.call, bestMatch.mismatch
+}
+
+func callString(method string, arguments Arguments, includeArgumentValues bool) string {
+ var argValsString string
+ if includeArgumentValues {
+ var argVals []string
+ for argIndex, arg := range arguments {
+ if _, ok := arg.(*FunctionalOptionsArgument); ok {
+ argVals = append(argVals, fmt.Sprintf("%d: %s", argIndex, arg))
+ continue
+ }
+ argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
+ }
+ argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
+ }
+
+ return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString)
+}
+
+// Called tells the mock object that a method has been called, and gets an array
+// of arguments to return. Panics if the call is unexpected (i.e. not preceded by
+// appropriate .On .Return() calls)
+// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
+func (m *Mock) Called(arguments ...interface{}) Arguments {
+ // get the calling function's name
+ pc, _, _, ok := runtime.Caller(1)
+ if !ok {
+ panic("Couldn't get the caller information")
+ }
+ functionPath := runtime.FuncForPC(pc).Name()
+ // Next four lines are required to use GCCGO function naming conventions.
+ // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
+ // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
+ // With GCCGO we need to remove interface information starting from pN<dd>.
+ re := regexp.MustCompile("\\.pN\\d+_")
+ if re.MatchString(functionPath) {
+ functionPath = re.Split(functionPath, -1)[0]
+ }
+ parts := strings.Split(functionPath, ".")
+ functionName := parts[len(parts)-1]
+ return m.MethodCalled(functionName, arguments...)
+}
+
+// MethodCalled tells the mock object that the given method has been called, and gets
+// an array of arguments to return. Panics if the call is unexpected (i.e. not preceded
+// by appropriate .On .Return() calls)
+// 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 {
+ // expected call found but it has already been called with repeatable times
+ if call != nil {
+ m.mutex.Unlock()
+ m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo())
+ }
+ // we have to fail here - because we don't know what to do
+ // as the return arguments. This is because:
+ //
+ // a) this is a totally unexpected call to this method,
+ // b) the arguments are not what was expected, or
+ // c) the developer has forgotten to add an accompanying On...Return pair.
+ closestCall, mismatch := m.findClosestCall(methodName, arguments...)
+ m.mutex.Unlock()
+
+ if closestCall != nil {
+ m.fail("\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 {
+ m.fail("\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())
+ }
+ }
+
+ for _, requirement := range call.requires {
+ if satisfied, _ := requirement.Parent.checkExpectation(requirement); !satisfied {
+ m.mutex.Unlock()
+ m.fail("mock: Unexpected Method Call\n-----------------------------\n\n%s\n\nMust not be called before%s:\n\n%s",
+ callString(call.Method, call.Arguments, true),
+ func() (s string) {
+ if requirement.totalCalls > 0 {
+ s = " another call of"
+ }
+ if call.Parent != requirement.Parent {
+ s += " method from another mock instance"
+ }
+ return
+ }(),
+ callString(requirement.Method, requirement.Arguments, true),
+ )
+ }
+ }
+
+ if call.Repeatability == 1 {
+ call.Repeatability = -1
+ } else if call.Repeatability > 1 {
+ call.Repeatability--
+ }
+ call.totalCalls++
+
+ // add the call
+ m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...))
+ m.mutex.Unlock()
+
+ // block if specified
+ if call.WaitFor != nil {
+ <-call.WaitFor
+ } else {
+ time.Sleep(call.waitTime)
+ }
+
+ m.mutex.Lock()
+ panicMsg := call.PanicMsg
+ m.mutex.Unlock()
+ if panicMsg != nil {
+ panic(*panicMsg)
+ }
+
+ m.mutex.Lock()
+ runFn := call.RunFn
+ m.mutex.Unlock()
+
+ if runFn != nil {
+ runFn(arguments)
+ }
+
+ m.mutex.Lock()
+ returnArgs := call.ReturnArguments
+ m.mutex.Unlock()
+
+ return returnArgs
+}
+
+/*
+ Assertions
+*/
+
+type assertExpectationser interface {
+ AssertExpectations(TestingT) bool
+}
+
+// AssertExpectationsForObjects asserts that everything specified with On and Return
+// of the specified objects was in fact called as expected.
+//
+// Calls may have occurred in any order.
+func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ for _, obj := range testObjects {
+ if m, ok := obj.(*Mock); ok {
+ t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
+ obj = m
+ }
+ m := obj.(assertExpectationser)
+ if !m.AssertExpectations(t) {
+ t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
+ return false
+ }
+ }
+ return true
+}
+
+// AssertExpectations asserts that everything specified with On and Return was
+// in fact called as expected. Calls may have occurred in any order.
+func (m *Mock) AssertExpectations(t TestingT) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ var failedExpectations int
+
+ // iterate through each expectation
+ expectedCalls := m.expectedCalls()
+ for _, expectedCall := range expectedCalls {
+ satisfied, reason := m.checkExpectation(expectedCall)
+ if !satisfied {
+ failedExpectations++
+ }
+ t.Logf(reason)
+ }
+
+ if failedExpectations != 0 {
+ t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
+ }
+
+ return failedExpectations == 0
+}
+
+func (m *Mock) checkExpectation(call *Call) (bool, string) {
+ if !call.optional && !m.methodWasCalled(call.Method, call.Arguments) && call.totalCalls == 0 {
+ return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
+ }
+ if call.Repeatability > 0 {
+ return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
+ }
+ return true, fmt.Sprintf("PASS:\t%s(%s)", call.Method, call.Arguments.String())
+}
+
+// AssertNumberOfCalls asserts that the method was called expectedCalls times.
+func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ var actualCalls int
+ for _, call := range m.calls() {
+ if call.Method == methodName {
+ actualCalls++
+ }
+ }
+ return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
+}
+
+// AssertCalled asserts that the method was called.
+// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
+func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ if !m.methodWasCalled(methodName, arguments) {
+ var calledWithArgs []string
+ for _, call := range m.calls() {
+ calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments))
+ }
+ if len(calledWithArgs) == 0 {
+ return assert.Fail(t, "Should have called with given arguments",
+ fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments))
+ }
+ return assert.Fail(t, "Should have called with given arguments",
+ fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n")))
+ }
+ return true
+}
+
+// AssertNotCalled asserts that the method was not called.
+// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
+func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ if m.methodWasCalled(methodName, arguments) {
+ return assert.Fail(t, "Should not have called with given arguments",
+ fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments))
+ }
+ return true
+}
+
+// IsMethodCallable checking that the method can be called
+// If the method was called more than `Repeatability` return false
+func (m *Mock) IsMethodCallable(t TestingT, methodName string, arguments ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ for _, v := range m.ExpectedCalls {
+ if v.Method != methodName {
+ continue
+ }
+ if len(arguments) != len(v.Arguments) {
+ continue
+ }
+ if v.Repeatability < v.totalCalls {
+ continue
+ }
+ if isArgsEqual(v.Arguments, arguments) {
+ return true
+ }
+ }
+ return false
+}
+
+// isArgsEqual compares arguments
+func isArgsEqual(expected Arguments, args []interface{}) bool {
+ if len(expected) != len(args) {
+ return false
+ }
+ for i, v := range args {
+ if !reflect.DeepEqual(expected[i], v) {
+ return false
+ }
+ }
+ return true
+}
+
+func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
+ for _, call := range m.calls() {
+ if call.Method == methodName {
+
+ _, differences := Arguments(expected).Diff(call.Arguments)
+
+ if differences == 0 {
+ // found the expected call
+ return true
+ }
+
+ }
+ }
+ // we didn't find the expected call
+ return false
+}
+
+func (m *Mock) expectedCalls() []*Call {
+ return append([]*Call{}, m.ExpectedCalls...)
+}
+
+func (m *Mock) calls() []Call {
+ return append([]Call{}, m.Calls...)
+}
+
+/*
+ Arguments
+*/
+
+// Arguments holds an array of method arguments or return values.
+type Arguments []interface{}
+
+const (
+ // Anything is used in Diff and Assert when the argument being tested
+ // shouldn't be taken into consideration.
+ Anything = "mock.Anything"
+)
+
+// AnythingOfTypeArgument is a string that contains the type of an argument
+// for use when type checking. Used in Diff and Assert.
+type AnythingOfTypeArgument string
+
+// AnythingOfType returns an AnythingOfTypeArgument object containing the
+// name of the type to check for. Used in Diff and Assert.
+//
+// For example:
+//
+// Assert(t, AnythingOfType("string"), AnythingOfType("int"))
+func AnythingOfType(t string) AnythingOfTypeArgument {
+ return AnythingOfTypeArgument(t)
+}
+
+// IsTypeArgument is a struct that contains the type of an argument
+// for use when type checking. This is an alternative to AnythingOfType.
+// Used in Diff and Assert.
+type IsTypeArgument struct {
+ t interface{}
+}
+
+// IsType returns an IsTypeArgument object containing the type to check for.
+// You can provide a zero-value of the type to check. This is an
+// alternative to AnythingOfType. Used in Diff and Assert.
+//
+// For example:
+// Assert(t, IsType(""), IsType(0))
+func IsType(t interface{}) *IsTypeArgument {
+ return &IsTypeArgument{t: t}
+}
+
+// FunctionalOptionsArgument is a struct that contains the type and value of an functional option argument
+// for use when type checking.
+type FunctionalOptionsArgument struct {
+ value interface{}
+}
+
+// String returns the string representation of FunctionalOptionsArgument
+func (f *FunctionalOptionsArgument) String() string {
+ var name string
+ tValue := reflect.ValueOf(f.value)
+ if tValue.Len() > 0 {
+ name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String()
+ }
+
+ return strings.Replace(fmt.Sprintf("%#v", f.value), "[]interface {}", name, 1)
+}
+
+// FunctionalOptions returns an FunctionalOptionsArgument object containing the functional option type
+// and the values to check of
+//
+// For example:
+// Assert(t, FunctionalOptions("[]foo.FunctionalOption", foo.Opt1(), foo.Opt2()))
+func FunctionalOptions(value ...interface{}) *FunctionalOptionsArgument {
+ return &FunctionalOptionsArgument{
+ value: value,
+ }
+}
+
+// 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)
+ expectTypeNilSupported := false
+ switch expectType.Kind() {
+ case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr:
+ expectTypeNilSupported = true
+ }
+
+ argType := reflect.TypeOf(argument)
+ var arg reflect.Value
+ if argType == nil {
+ arg = reflect.New(expectType).Elem()
+ } else {
+ arg = reflect.ValueOf(argument)
+ }
+
+ if argType == nil && !expectTypeNilSupported {
+ panic(errors.New("attempting to call matcher with nil for non-nil expected type"))
+ }
+ if argType == nil || argType.AssignableTo(expectType) {
+ result := f.fn.Call([]reflect.Value{arg})
+ return result[0].Bool()
+ }
+ return false
+}
+
+func (f argumentMatcher) String() string {
+ return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).String())
+}
+
+// MatchedBy can be used to match a mock call based on only certain properties
+// from a complex struct or some calculation. It takes a function that will be
+// evaluated with the called argument and will return true when there's a match
+// and false otherwise.
+//
+// Example:
+// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" }))
+//
+// |fn|, must be a function accepting a single argument (of the expected type)
+// which returns a bool. If |fn| doesn't match the required signature,
+// MatchedBy() 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) {
+ panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args)))
+ }
+ return args[index]
+}
+
+// Is gets whether the objects match the arguments specified.
+func (args Arguments) Is(objects ...interface{}) bool {
+ for i, obj := range args {
+ if obj != objects[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// Diff gets a string describing the differences between the arguments
+// and the specified objects.
+//
+// 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
+
+ output := "\n"
+ var differences int
+
+ maxArgCount := len(args)
+ if len(objects) > maxArgCount {
+ maxArgCount = len(objects)
+ }
+
+ for i := 0; i < maxArgCount; i++ {
+ var actual, expected interface{}
+ var actualFmt, expectedFmt string
+
+ if len(objects) <= i {
+ actual = "(Missing)"
+ actualFmt = "(Missing)"
+ } else {
+ actual = objects[i]
+ actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
+ }
+
+ if len(args) <= i {
+ expected = "(Missing)"
+ expectedFmt = "(Missing)"
+ } else {
+ expected = args[i]
+ expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
+ }
+
+ if matcher, ok := expected.(argumentMatcher); ok {
+ var matches bool
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
+ }
+ }()
+ matches = matcher.Matches(actual)
+ }()
+ if matches {
+ output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
+ } else {
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, 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)) {
+ // not match
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
+ }
+ } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) {
+ t := expected.(*IsTypeArgument).t
+ if reflect.TypeOf(t) != reflect.TypeOf(actual) {
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt)
+ }
+ } else if reflect.TypeOf(expected) == reflect.TypeOf((*FunctionalOptionsArgument)(nil)) {
+ t := expected.(*FunctionalOptionsArgument).value
+
+ var name string
+ tValue := reflect.ValueOf(t)
+ if tValue.Len() > 0 {
+ name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String()
+ }
+
+ tName := reflect.TypeOf(t).Name()
+ if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 {
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt)
+ } else {
+ if ef, af := assertOpts(t, actual); ef == "" && af == "" {
+ // match
+ output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName)
+ } else {
+ // not match
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef)
+ }
+ }
+ } else {
+ // normal checking
+
+ if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
+ // match
+ output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
+ } else {
+ // not match
+ differences++
+ output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
+ }
+ }
+
+ }
+
+ if differences == 0 {
+ return "No differences.", differences
+ }
+
+ return output, differences
+}
+
+// Assert compares the arguments with the specified objects and fails if
+// they do not exactly match.
+func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ // get the differences
+ diff, diffCount := args.Diff(objects)
+
+ if diffCount == 0 {
+ return true
+ }
+
+ // there are differences... report them...
+ t.Logf(diff)
+ t.Errorf("%sArguments do not match.", assert.CallerInfo())
+
+ return false
+}
+
+// String gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+//
+// If no index is provided, String() returns a complete string representation
+// of the arguments.
+func (args Arguments) String(indexOrNil ...int) string {
+ if len(indexOrNil) == 0 {
+ // normal String() method - return a string representation of the args
+ var argsStr []string
+ for _, arg := range args {
+ argsStr = append(argsStr, fmt.Sprintf("%T", arg)) // handles nil nicely
+ }
+ return strings.Join(argsStr, ",")
+ } else if len(indexOrNil) == 1 {
+ // Index has been specified - get the argument at that index
+ index := indexOrNil[0]
+ var s string
+ var ok bool
+ if s, ok = args.Get(index).(string); !ok {
+ panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index)))
+ }
+ return s
+ }
+
+ panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
+}
+
+// Int gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Int(index int) int {
+ var s int
+ var ok bool
+ if s, ok = args.Get(index).(int); !ok {
+ panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
+
+// Error gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Error(index int) error {
+ obj := args.Get(index)
+ var s error
+ var ok bool
+ if obj == nil {
+ return nil
+ }
+ if s, ok = obj.(error); !ok {
+ panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
+
+// Bool gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Bool(index int) bool {
+ var s bool
+ var ok bool
+ if s, ok = args.Get(index).(bool); !ok {
+ panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
+
+func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
+ t := reflect.TypeOf(v)
+ k := t.Kind()
+
+ if k == reflect.Ptr {
+ t = t.Elem()
+ k = t.Kind()
+ }
+ return t, k
+}
+
+func diffArguments(expected Arguments, actual Arguments) string {
+ if len(expected) != len(actual) {
+ return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual))
+ }
+
+ for x := range expected {
+ if diffString := diff(expected[x], actual[x]); diffString != "" {
+ return fmt.Sprintf("Difference found in argument %v:\n\n%s", x, diffString)
+ }
+ }
+
+ return ""
+}
+
+// diff returns a diff of both values as long as both are of the same type and
+// are a struct, map, slice or array. Otherwise it returns an empty string.
+func diff(expected interface{}, actual interface{}) string {
+ if expected == nil || actual == nil {
+ return ""
+ }
+
+ et, ek := typeAndKind(expected)
+ at, _ := typeAndKind(actual)
+
+ if et != at {
+ return ""
+ }
+
+ if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
+ return ""
+ }
+
+ e := spewConfig.Sdump(expected)
+ a := spewConfig.Sdump(actual)
+
+ diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
+ A: difflib.SplitLines(e),
+ B: difflib.SplitLines(a),
+ FromFile: "Expected",
+ FromDate: "",
+ ToFile: "Actual",
+ ToDate: "",
+ Context: 1,
+ })
+
+ return diff
+}
+
+var spewConfig = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+}
+
+type tHelper interface {
+ Helper()
+}
+
+func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
+ expectedOpts := reflect.ValueOf(expected)
+ actualOpts := reflect.ValueOf(actual)
+ var expectedNames []string
+ for i := 0; i < expectedOpts.Len(); i++ {
+ expectedNames = append(expectedNames, funcName(expectedOpts.Index(i).Interface()))
+ }
+ var actualNames []string
+ for i := 0; i < actualOpts.Len(); i++ {
+ actualNames = append(actualNames, funcName(actualOpts.Index(i).Interface()))
+ }
+ if !assert.ObjectsAreEqual(expectedNames, actualNames) {
+ expectedFmt = fmt.Sprintf("%v", expectedNames)
+ actualFmt = fmt.Sprintf("%v", actualNames)
+ return
+ }
+
+ for i := 0; i < expectedOpts.Len(); i++ {
+ expectedOpt := expectedOpts.Index(i).Interface()
+ actualOpt := actualOpts.Index(i).Interface()
+
+ expectedFunc := expectedNames[i]
+ actualFunc := actualNames[i]
+ if expectedFunc != actualFunc {
+ expectedFmt = expectedFunc
+ actualFmt = actualFunc
+ return
+ }
+
+ ot := reflect.TypeOf(expectedOpt)
+ var expectedValues []reflect.Value
+ var actualValues []reflect.Value
+ if ot.NumIn() == 0 {
+ return
+ }
+
+ for i := 0; i < ot.NumIn(); i++ {
+ vt := ot.In(i).Elem()
+ expectedValues = append(expectedValues, reflect.New(vt))
+ actualValues = append(actualValues, reflect.New(vt))
+ }
+
+ reflect.ValueOf(expectedOpt).Call(expectedValues)
+ reflect.ValueOf(actualOpt).Call(actualValues)
+
+ for i := 0; i < ot.NumIn(); i++ {
+ if !assert.ObjectsAreEqual(expectedValues[i].Interface(), actualValues[i].Interface()) {
+ expectedFmt = fmt.Sprintf("%s %+v", expectedNames[i], expectedValues[i].Interface())
+ actualFmt = fmt.Sprintf("%s %+v", expectedNames[i], actualValues[i].Interface())
+ return
+ }
+ }
+ }
+
+ return "", ""
+}
+
+func funcName(opt interface{}) string {
+ n := runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name()
+ return strings.TrimSuffix(path.Base(n), path.Ext(n))
+}
diff --git a/vendor/github.com/stretchr/testify/mock/mock_test.go b/vendor/github.com/stretchr/testify/mock/mock_test.go
new file mode 100644
index 0000000000..9ceebbc44e
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/mock/mock_test.go
@@ -0,0 +1,2141 @@
+package mock
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+/*
+ Test objects
+*/
+
+// ExampleInterface represents an example interface.
+type ExampleInterface interface {
+ TheExampleMethod(a, b, c int) (int, error)
+}
+
+// TestExampleImplementation is a test implementation of ExampleInterface
+type TestExampleImplementation struct {
+ Mock
+}
+
+func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) {
+ args := i.Called(a, b, c)
+ return args.Int(0), errors.New("Whoops")
+}
+
+type options struct {
+ num int
+ str string
+}
+
+type OptionFn func(*options)
+
+func OpNum(n int) OptionFn {
+ return func(o *options) {
+ o.num = n
+ }
+}
+
+func OpStr(s string) OptionFn {
+ return func(o *options) {
+ o.str = s
+ }
+}
+func (i *TestExampleImplementation) TheExampleMethodFunctionalOptions(x string, opts ...OptionFn) error {
+ args := i.Called(x, opts)
+ return args.Error(0)
+}
+
+//go:noinline
+func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
+ i.Called(yesorno)
+}
+
+type ExampleType struct {
+ ran bool
+}
+
+func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error {
+ args := i.Called(et)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethod4(v ExampleInterface) error {
+ args := i.Called(v)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethod5(ch chan struct{}) error {
+ args := i.Called(ch)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethod6(m map[string]bool) error {
+ args := i.Called(m)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethod7(slice []bool) error {
+ args := i.Called(slice)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error {
+ args := i.Called(fn)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethodVariadic(a ...int) error {
+ args := i.Called(a)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...interface{}) error {
+ args := i.Called(a)
+ return args.Error(0)
+}
+
+func (i *TestExampleImplementation) TheExampleMethodMixedVariadic(a int, b ...int) error {
+ args := i.Called(a, b)
+ return args.Error(0)
+}
+
+type ExampleFuncType func(string) error
+
+func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error {
+ args := i.Called(fn)
+ return args.Error(0)
+}
+
+// MockTestingT mocks a test struct
+type MockTestingT struct {
+ logfCount, errorfCount, failNowCount int
+}
+
+const mockTestingTFailNowCalled = "FailNow was called"
+
+func (m *MockTestingT) Logf(string, ...interface{}) {
+ m.logfCount++
+}
+
+func (m *MockTestingT) Errorf(string, ...interface{}) {
+ m.errorfCount++
+}
+
+// FailNow mocks the FailNow call.
+// It panics in order to mimic the FailNow behavior in the sense that
+// the execution stops.
+// When expecting this method, the call that invokes it should use the following code:
+//
+// assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {...})
+func (m *MockTestingT) FailNow() {
+ m.failNowCount++
+
+ // this function should panic now to stop the execution as expected
+ panic(mockTestingTFailNowCalled)
+}
+
+/*
+ Mock
+*/
+
+func Test_Mock_TestData(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ if assert.NotNil(t, mockedService.TestData()) {
+
+ mockedService.TestData().Set("something", 123)
+ assert.Equal(t, 123, mockedService.TestData().Get("something").Data())
+ }
+}
+
+func Test_Mock_On(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.On("TheExampleMethod")
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, "TheExampleMethod", c.Method)
+}
+
+func Test_Mock_Chained_On(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ // determine our current line number so we can assert the expected calls callerInfo properly
+ _, filename, line, _ := runtime.Caller(0)
+ mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(0).
+ On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
+ Return(nil)
+
+ expectedCalls := []*Call{
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethod",
+ Arguments: []interface{}{1, 2, 3},
+ ReturnArguments: []interface{}{0},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)},
+ },
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethod3",
+ Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
+ ReturnArguments: []interface{}{nil},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
+ },
+ }
+ assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
+}
+
+func Test_Mock_On_WithArgs(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.On("TheExampleMethod", 1, 2, 3, 4)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, "TheExampleMethod", c.Method)
+ assert.Equal(t, Arguments{1, 2, 3, 4}, c.Arguments)
+}
+
+func Test_Mock_On_WithFuncArg(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethodFunc", AnythingOfType("func(string) error")).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, "TheExampleMethodFunc", c.Method)
+ assert.Equal(t, 1, len(c.Arguments))
+ assert.Equal(t, AnythingOfType("func(string) error"), c.Arguments[0])
+
+ fn := func(string) error { return nil }
+
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodFunc(fn)
+ })
+}
+
+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_WithArgMatcherThatPanics(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool {
+ panic("try to lock mockedService")
+ })).Return()
+
+ defer func() {
+ assertedExpectations := make(chan struct{})
+ go func() {
+ tt := new(testing.T)
+ mockedService.AssertExpectations(tt)
+ close(assertedExpectations)
+ }()
+ select {
+ case <-assertedExpectations:
+ case <-time.After(time.Second):
+ t.Fatal("AssertExpectations() deadlocked, did the panic leave mockedService locked?")
+ }
+ }()
+
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethod2(false)
+ })
+}
+
+func TestMock_WithTest(t *testing.T) {
+ var (
+ mockedService TestExampleImplementation
+ mockedTest MockTestingT
+ )
+
+ mockedService.Test(&mockedTest)
+ mockedService.On("TheExampleMethod", 1, 2, 3).Return(0, nil)
+
+ // Test that on an expected call, the test was not failed
+
+ mockedService.TheExampleMethod(1, 2, 3)
+
+ // Assert that Errorf and FailNow were not called
+ assert.Equal(t, 0, mockedTest.errorfCount)
+ assert.Equal(t, 0, mockedTest.failNowCount)
+
+ // Test that on unexpected call, the mocked test was called to fail the test
+
+ assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {
+ mockedService.TheExampleMethod(1, 1, 1)
+ })
+
+ // Assert that Errorf and FailNow were called once
+ assert.Equal(t, 1, mockedTest.errorfCount)
+ assert.Equal(t, 1, mockedTest.failNowCount)
+}
+
+func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod3",
+ MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == true }),
+ ).Return(nil)
+
+ mockedService.On("TheExampleMethod3",
+ MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == false }),
+ ).Return(errors.New("error"))
+
+ mockedService.On("TheExampleMethod3",
+ MatchedBy(func(a *ExampleType) bool { return a == nil }),
+ ).Return(errors.New("error2"))
+
+ assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil)
+ assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error")
+ assert.EqualError(t, mockedService.TheExampleMethod3(nil), "error2")
+}
+
+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 != nil && a("string") == fixture1 }),
+ ).Return(errors.New("fixture1"))
+
+ mockedService.On("TheExampleMethodFunc",
+ MatchedBy(func(a func(string) error) bool { return a != nil && a("string") == fixture2 }),
+ ).Return(errors.New("fixture2"))
+
+ mockedService.On("TheExampleMethodFunc",
+ MatchedBy(func(a func(string) error) bool { return a == nil }),
+ ).Return(errors.New("fixture3"))
+
+ assert.EqualError(t, mockedService.TheExampleMethodFunc(
+ func(string) error { return fixture1 }), "fixture1")
+ assert.EqualError(t, mockedService.TheExampleMethodFunc(
+ func(string) error { return fixture2 }), "fixture2")
+ assert.EqualError(t, mockedService.TheExampleMethodFunc(nil), "fixture3")
+}
+
+func Test_Mock_On_WithInterfaceArgMatcher(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod4",
+ MatchedBy(func(a ExampleInterface) bool { return a == nil }),
+ ).Return(errors.New("fixture1"))
+
+ assert.EqualError(t, mockedService.TheExampleMethod4(nil), "fixture1")
+}
+
+func Test_Mock_On_WithChannelArgMatcher(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod5",
+ MatchedBy(func(ch chan struct{}) bool { return ch == nil }),
+ ).Return(errors.New("fixture1"))
+
+ assert.EqualError(t, mockedService.TheExampleMethod5(nil), "fixture1")
+}
+
+func Test_Mock_On_WithMapArgMatcher(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod6",
+ MatchedBy(func(m map[string]bool) bool { return m == nil }),
+ ).Return(errors.New("fixture1"))
+
+ assert.EqualError(t, mockedService.TheExampleMethod6(nil), "fixture1")
+}
+
+func Test_Mock_On_WithSliceArgMatcher(t *testing.T) {
+ var mockedService TestExampleImplementation
+
+ mockedService.On("TheExampleMethod7",
+ MatchedBy(func(slice []bool) bool { return slice == nil }),
+ ).Return(errors.New("fixture1"))
+
+ assert.EqualError(t, mockedService.TheExampleMethod7(nil), "fixture1")
+}
+
+func Test_Mock_On_WithVariadicFunc(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethodVariadic", []int{1, 2, 3}).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, 1, len(c.Arguments))
+ assert.Equal(t, []int{1, 2, 3}, c.Arguments[0])
+
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodVariadic(1, 2, 3)
+ })
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethodVariadic(1, 2)
+ })
+
+}
+
+func Test_Mock_On_WithMixedVariadicFunc(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethodMixedVariadic", 1, []int{2, 3, 4}).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, 2, len(c.Arguments))
+ assert.Equal(t, 1, c.Arguments[0])
+ assert.Equal(t, []int{2, 3, 4}, c.Arguments[1])
+
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 4)
+ })
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 5)
+ })
+
+}
+
+func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, 1, len(c.Arguments))
+ assert.Equal(t, []interface{}{1, 2, 3}, c.Arguments[0])
+
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodVariadicInterface(1, 2, 3)
+ })
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethodVariadicInterface(1, 2)
+ })
+
+}
+
+func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ var expected []interface{}
+ c := mockedService.
+ On("TheExampleMethodVariadicInterface", expected).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, 1, len(c.Arguments))
+ assert.Equal(t, expected, c.Arguments[0])
+
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodVariadicInterface()
+ })
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethodVariadicInterface(1, 2)
+ })
+
+}
+
+func Test_Mock_On_WithFuncPanics(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ assert.Panics(t, func() {
+ mockedService.On("TheExampleMethodFunc", func(string) error { return nil })
+ })
+}
+
+func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")).
+ Return(nil)
+
+ assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+ assert.Equal(t, 1, len(c.Arguments))
+ assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), c.Arguments[0])
+
+ fn := func(string) error { return nil }
+ assert.NotPanics(t, func() {
+ mockedService.TheExampleMethodFuncType(fn)
+ })
+}
+
+func Test_Mock_Unset(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ call := mockedService.
+ On("TheExampleMethodFuncType", "argA").
+ Return("blah")
+
+ found, foundCall := mockedService.findExpectedCall("TheExampleMethodFuncType", "argA")
+ require.NotEqual(t, -1, found)
+ require.Equal(t, foundCall, call)
+
+ call.Unset()
+
+ found, foundCall = mockedService.findExpectedCall("TheExampleMethodFuncType", "argA")
+ require.Equal(t, -1, found)
+
+ var expectedCall *Call
+ require.Equal(t, expectedCall, foundCall)
+
+ fn := func(string) error { return nil }
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethodFuncType(fn)
+ })
+}
+
+// Since every time you call On it creates a new object
+// the last time you call Unset it will only unset the last call
+func Test_Mock_Chained_UnsetOnlyUnsetsLastCall(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ // determine our current line number so we can assert the expected calls callerInfo properly
+ _, filename, line, _ := runtime.Caller(0)
+ mockedService.
+ On("TheExampleMethod1", 1, 1).
+ Return(0).
+ On("TheExampleMethod2", 2, 2).
+ On("TheExampleMethod3", 3, 3, 3).
+ Return(nil).
+ Unset()
+
+ expectedCalls := []*Call{
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethod1",
+ Arguments: []interface{}{1, 1},
+ ReturnArguments: []interface{}{0},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)},
+ },
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethod2",
+ Arguments: []interface{}{2, 2},
+ ReturnArguments: []interface{}{},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
+ },
+ }
+ assert.Equal(t, 2, len(expectedCalls))
+ assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
+}
+
+func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ mock1 := mockedService.
+ On("TheExampleMethod1", 1, 1).
+ Return(1)
+
+ assert.Equal(t, 1, len(mockedService.ExpectedCalls))
+ mock1.Unset()
+ assert.Equal(t, 0, len(mockedService.ExpectedCalls))
+
+ assert.Panics(t, func() {
+ mock1.Unset()
+ })
+
+ assert.Equal(t, 0, len(mockedService.ExpectedCalls))
+}
+
+func Test_Mock_UnsetByOnMethodSpec(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ mock1 := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(0, nil)
+
+ assert.Equal(t, 1, len(mockedService.ExpectedCalls))
+ mock1.On("TheExampleMethod", 1, 2, 3).
+ Return(0, nil).Unset()
+
+ assert.Equal(t, 0, len(mockedService.ExpectedCalls))
+
+ assert.Panics(t, func() {
+ mock1.Unset()
+ })
+
+ assert.Equal(t, 0, len(mockedService.ExpectedCalls))
+}
+
+func Test_Mock_UnsetByOnMethodSpecAmongOthers(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ _, filename, line, _ := runtime.Caller(0)
+ mock1 := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(0, nil).
+ On("TheExampleMethodVariadic", 1, 2, 3, 4, 5).Once().
+ Return(nil)
+ mock1.
+ On("TheExampleMethodFuncType", Anything).
+ Return(nil)
+
+ assert.Equal(t, 3, len(mockedService.ExpectedCalls))
+ mock1.On("TheExampleMethod", 1, 2, 3).
+ Return(0, nil).Unset()
+
+ assert.Equal(t, 2, len(mockedService.ExpectedCalls))
+
+ expectedCalls := []*Call{
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethodVariadic",
+ Repeatability: 1,
+ Arguments: []interface{}{1, 2, 3, 4, 5},
+ ReturnArguments: []interface{}{nil},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
+ },
+ {
+ Parent: &mockedService.Mock,
+ Method: "TheExampleMethodFuncType",
+ Arguments: []interface{}{Anything},
+ ReturnArguments: []interface{}{nil},
+ callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+7)},
+ },
+ }
+
+ assert.Equal(t, 2, len(mockedService.ExpectedCalls))
+ assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
+}
+
+func Test_Mock_Unset_WithFuncPanics(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+ mock1 := mockedService.On("TheExampleMethod", 1)
+ mock1.Arguments = append(mock1.Arguments, func(string) error { return nil })
+
+ assert.Panics(t, func() {
+ mock1.Unset()
+ })
+}
+
+func Test_Mock_Return(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethod", "A", "B", true).
+ Return(1, "two", true)
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.Nil(t, call.WaitFor)
+}
+
+func Test_Mock_Panic(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethod", "A", "B", true).
+ Panic("panic message for example method")
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.Equal(t, 0, call.Repeatability)
+ assert.Equal(t, "panic message for example method", *call.PanicMsg)
+ assert.Nil(t, call.WaitFor)
+}
+
+func Test_Mock_Return_WaitUntil(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+ ch := time.After(time.Second)
+
+ c := mockedService.Mock.
+ On("TheExampleMethod", "A", "B", true).
+ WaitUntil(ch).
+ Return(1, "two", true)
+
+ // assert that the call was created
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.Equal(t, ch, call.WaitFor)
+}
+
+func Test_Mock_Return_After(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.Mock.
+ On("TheExampleMethod", "A", "B", true).
+ Return(1, "two", true).
+ After(time.Second)
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.NotEqual(t, nil, call.WaitFor)
+
+}
+
+func Test_Mock_Return_Run(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ fn := func(args Arguments) {
+ arg := args.Get(0).(*ExampleType)
+ arg.ran = true
+ }
+
+ c := mockedService.Mock.
+ On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
+ Return(nil).
+ Run(fn)
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod3", call.Method)
+ assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
+ assert.Equal(t, nil, call.ReturnArguments[0])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.NotEqual(t, nil, call.WaitFor)
+ assert.NotNil(t, call.Run)
+
+ et := ExampleType{}
+ assert.Equal(t, false, et.ran)
+ mockedService.TheExampleMethod3(&et)
+ assert.Equal(t, true, et.ran)
+}
+
+func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) {
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+ f := func(args Arguments) {
+ arg := args.Get(0).(*ExampleType)
+ arg.ran = true
+ }
+
+ c := mockedService.Mock.
+ On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
+ Run(f).
+ Return(nil)
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod3", call.Method)
+ assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
+ assert.Equal(t, nil, call.ReturnArguments[0])
+ assert.Equal(t, 0, call.Repeatability)
+ assert.NotEqual(t, nil, call.WaitFor)
+ assert.NotNil(t, call.Run)
+}
+
+func Test_Mock_Return_Once(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.On("TheExampleMethod", "A", "B", true).
+ Return(1, "two", true).
+ Once()
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 1, call.Repeatability)
+ assert.Nil(t, call.WaitFor)
+}
+
+func Test_Mock_Return_Twice(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethod", "A", "B", true).
+ Return(1, "two", true).
+ Twice()
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 2, call.Repeatability)
+ assert.Nil(t, call.WaitFor)
+}
+
+func Test_Mock_Return_Times(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethod", "A", "B", true).
+ Return(1, "two", true).
+ Times(5)
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 5, call.Repeatability)
+ assert.Nil(t, call.WaitFor)
+}
+
+func Test_Mock_Return_Nothing(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ c := mockedService.
+ On("TheExampleMethod", "A", "B", true).
+ Return()
+
+ require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
+
+ call := mockedService.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 0, len(call.ReturnArguments))
+}
+
+func Test_Mock_Return_NotBefore_In_Order(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ b := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil)
+ c := mockedService.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(b)
+
+ require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod(1, 2, 3)
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod2(true)
+ })
+}
+
+func Test_Mock_Return_NotBefore_Out_Of_Order(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ b := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil).Twice()
+ c := mockedService.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(b)
+
+ require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
+
+ expectedPanicString := `mock: Unexpected Method Call
+-----------------------------
+
+TheExampleMethod2(bool)
+ 0: true
+
+Must not be called before:
+
+TheExampleMethod(int,int,int)
+ 0: 1
+ 1: 2
+ 2: 3`
+ require.PanicsWithValue(t, expectedPanicString, func() {
+ mockedService.TheExampleMethod2(true)
+ })
+}
+
+func Test_Mock_Return_NotBefore_Not_Enough_Times(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ b := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil).Twice()
+ c := mockedService.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(b)
+
+ require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
+
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod(1, 2, 3)
+ })
+ expectedPanicString := `mock: Unexpected Method Call
+-----------------------------
+
+TheExampleMethod2(bool)
+ 0: true
+
+Must not be called before another call of:
+
+TheExampleMethod(int,int,int)
+ 0: 1
+ 1: 2
+ 2: 3`
+ require.PanicsWithValue(t, expectedPanicString, func() {
+ mockedService.TheExampleMethod2(true)
+ })
+}
+
+func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) {
+ var (
+ mockedService1 = new(TestExampleImplementation)
+ mockedService2 = new(TestExampleImplementation)
+ )
+
+ b := mockedService1.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil)
+ c := mockedService2.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(b)
+
+ require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls)
+ require.NotPanics(t, func() {
+ mockedService1.TheExampleMethod(1, 2, 3)
+ })
+ require.NotPanics(t, func() {
+ mockedService2.TheExampleMethod2(true)
+ })
+}
+func Test_Mock_Return_NotBefore_Different_Mock_Out_Of_Order(t *testing.T) {
+ var (
+ mockedService1 = new(TestExampleImplementation)
+ mockedService2 = new(TestExampleImplementation)
+ )
+
+ b := mockedService1.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil)
+ c := mockedService2.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(b)
+
+ require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls)
+
+ expectedPanicString := `mock: Unexpected Method Call
+-----------------------------
+
+TheExampleMethod2(bool)
+ 0: true
+
+Must not be called before method from another mock instance:
+
+TheExampleMethod(int,int,int)
+ 0: 1
+ 1: 2
+ 2: 3`
+ require.PanicsWithValue(t, expectedPanicString, func() {
+ mockedService2.TheExampleMethod2(true)
+ })
+}
+
+func Test_Mock_Return_NotBefore_In_Order_With_Non_Dependant(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ a := mockedService.
+ On("TheExampleMethod", 1, 2, 3).
+ Return(4, nil)
+ b := mockedService.
+ On("TheExampleMethod", 4, 5, 6).
+ Return(4, nil)
+ c := mockedService.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(a, b)
+ d := mockedService.
+ On("TheExampleMethod7", []bool{}).Return(nil)
+
+ require.Equal(t, []*Call{a, b, c, d}, mockedService.ExpectedCalls)
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod7([]bool{})
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod(1, 2, 3)
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod7([]bool{})
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod(4, 5, 6)
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod7([]bool{})
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod2(true)
+ })
+ require.NotPanics(t, func() {
+ mockedService.TheExampleMethod7([]bool{})
+ })
+}
+
+func Test_Mock_Return_NotBefore_Orphan_Call(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ require.PanicsWithValue(t, "not before calls must be created with Mock.On()", func() {
+ mockedService.
+ On("TheExampleMethod2", true).
+ Return().
+ NotBefore(&Call{Method: "Not", Arguments: Arguments{"how", "it's"}, ReturnArguments: Arguments{"done"}})
+ })
+}
+
+func Test_Mock_findExpectedCall(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two")
+ m.On("Two", 3).Return("three")
+
+ f, c := m.findExpectedCall("Two", 3)
+
+ if assert.Equal(t, 2, f) {
+ if assert.NotNil(t, c) {
+ assert.Equal(t, "Two", c.Method)
+ assert.Equal(t, 3, c.Arguments[0])
+ assert.Equal(t, "three", c.ReturnArguments[0])
+ }
+ }
+
+}
+
+func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two")
+ m.On("Two", 3).Return("three")
+
+ f, _ := m.findExpectedCall("Two")
+
+ assert.Equal(t, -1, f)
+
+}
+
+func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two").Once()
+ m.On("Two", 3).Return("three").Twice()
+ m.On("Two", 3).Return("three").Times(8)
+
+ f, c := m.findExpectedCall("Two", 3)
+
+ if assert.Equal(t, 2, f) {
+ if assert.NotNil(t, c) {
+ assert.Equal(t, "Two", c.Method)
+ assert.Equal(t, 3, c.Arguments[0])
+ assert.Equal(t, "three", c.ReturnArguments[0])
+ }
+ }
+
+ c = m.On("Once", 1).Return("one").Once()
+ c.Repeatability = -1
+ f, c = m.findExpectedCall("Once", 1)
+ if assert.Equal(t, -1, f) {
+ if assert.NotNil(t, c) {
+ assert.Equal(t, "Once", c.Method)
+ assert.Equal(t, 1, c.Arguments[0])
+ assert.Equal(t, "one", c.ReturnArguments[0])
+ }
+ }
+}
+
+func Test_callString(t *testing.T) {
+
+ assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false))
+ assert.Equal(t, `Method(<nil>)`, callString("Method", []interface{}{nil}, false))
+
+}
+
+func Test_Mock_Called(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true)
+
+ returnArguments := mockedService.Called(1, 2, 3)
+
+ if assert.Equal(t, 1, len(mockedService.Calls)) {
+ assert.Equal(t, "Test_Mock_Called", mockedService.Calls[0].Method)
+ assert.Equal(t, 1, mockedService.Calls[0].Arguments[0])
+ assert.Equal(t, 2, mockedService.Calls[0].Arguments[1])
+ assert.Equal(t, 3, mockedService.Calls[0].Arguments[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments)) {
+ assert.Equal(t, 5, returnArguments[0])
+ assert.Equal(t, "6", returnArguments[1])
+ assert.Equal(t, true, returnArguments[2])
+ }
+
+}
+
+func asyncCall(m *Mock, ch chan Arguments) {
+ ch <- m.Called(1, 2, 3)
+}
+
+func Test_Mock_Called_blocks(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond)
+
+ ch := make(chan Arguments)
+
+ go asyncCall(&mockedService.Mock, ch)
+
+ select {
+ case <-ch:
+ t.Fatal("should have waited")
+ case <-time.After(1 * time.Millisecond):
+ }
+
+ returnArguments := <-ch
+
+ if assert.Equal(t, 1, len(mockedService.Mock.Calls)) {
+ assert.Equal(t, "asyncCall", mockedService.Mock.Calls[0].Method)
+ assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0])
+ assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1])
+ assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments)) {
+ assert.Equal(t, 5, returnArguments[0])
+ assert.Equal(t, "6", returnArguments[1])
+ assert.Equal(t, true, returnArguments[2])
+ }
+
+}
+
+func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.
+ On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
+ Return(5, "6", true).
+ Once()
+ mockedService.
+ On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
+ Return(-1, "hi", false)
+
+ returnArguments1 := mockedService.Called(1, 2, 3)
+ returnArguments2 := mockedService.Called(1, 2, 3)
+
+ if assert.Equal(t, 2, len(mockedService.Calls)) {
+ assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[0].Method)
+ assert.Equal(t, 1, mockedService.Calls[0].Arguments[0])
+ assert.Equal(t, 2, mockedService.Calls[0].Arguments[1])
+ assert.Equal(t, 3, mockedService.Calls[0].Arguments[2])
+
+ assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[1].Method)
+ assert.Equal(t, 1, mockedService.Calls[1].Arguments[0])
+ assert.Equal(t, 2, mockedService.Calls[1].Arguments[1])
+ assert.Equal(t, 3, mockedService.Calls[1].Arguments[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments1)) {
+ assert.Equal(t, 5, returnArguments1[0])
+ assert.Equal(t, "6", returnArguments1[1])
+ assert.Equal(t, true, returnArguments1[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments2)) {
+ assert.Equal(t, -1, returnArguments2[0])
+ assert.Equal(t, "hi", returnArguments2[1])
+ assert.Equal(t, false, returnArguments2[2])
+ }
+
+}
+
+func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4)
+
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethod(1, 2, 3)
+ })
+
+}
+
+func Test_Mock_Called_Unexpected(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ // make sure it panics if no expectation was made
+ assert.Panics(t, func() {
+ mockedService.Called(1, 2, 3)
+ }, "Calling unexpected method should panic")
+
+}
+
+func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
+
+ var mockedService1 = new(TestExampleImplementation)
+ var mockedService2 = new(TestExampleImplementation)
+ var mockedService3 = new(TestExampleImplementation)
+ var mockedService4 = new(TestExampleImplementation) // No expectations does not cause a panic
+
+ mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
+ mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
+ mockedService3.On("Test_AssertExpectationsForObjects_Helper", 3).Return()
+
+ mockedService1.Called(1)
+ mockedService2.Called(2)
+ mockedService3.Called(3)
+
+ assert.True(t, AssertExpectationsForObjects(t, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock, &mockedService4.Mock))
+ assert.True(t, AssertExpectationsForObjects(t, mockedService1, mockedService2, mockedService3, mockedService4))
+
+}
+
+func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
+
+ var mockedService1 = new(TestExampleImplementation)
+ var mockedService2 = new(TestExampleImplementation)
+ var mockedService3 = new(TestExampleImplementation)
+
+ mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return()
+ mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return()
+ mockedService3.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return()
+
+ mockedService1.Called(1)
+ mockedService3.Called(3)
+
+ tt := new(testing.T)
+ assert.False(t, AssertExpectationsForObjects(tt, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock))
+ assert.False(t, AssertExpectationsForObjects(tt, mockedService1, mockedService2, mockedService3))
+
+}
+
+func Test_Mock_AssertExpectations(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7)
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Called(1, 2, 3)
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectations_Placeholder_NoArgs(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(5, 6, 7).Once()
+ mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(7, 6, 5)
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Called()
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectations_Placeholder(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertExpectations_Placeholder", 1, 2, 3).Return(5, 6, 7).Once()
+ mockedService.On("Test_Mock_AssertExpectations_Placeholder", 3, 2, 1).Return(7, 6, 5)
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Called(1, 2, 3)
+
+ // now assert expectations
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make call to the second expectation
+ mockedService.Called(3, 2, 1)
+
+ // now assert expectations again
+ assert.True(t, mockedService.AssertExpectations(tt))
+}
+
+func Test_Mock_AssertExpectations_With_Pointers(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{1}).Return(1)
+ mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{2}).Return(2)
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ s := struct{ Foo int }{1}
+ // make the calls now
+ mockedService.Called(&s)
+ s.Foo = 2
+ mockedService.Called(&s)
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once()
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.TheExampleMethod3(&ExampleType{})
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectationsFunctionalOptionsType(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
+ mockedService.TheExampleMethodFunctionalOptions("test", OpNum(1), OpStr("foo"))
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions()).Return(nil).Once()
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.TheExampleMethodFunctionalOptions("test")
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice()
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Called(1, 2, 3)
+
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ mockedService.Called(1, 2, 3)
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7)
+ mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7)
+
+ args1 := mockedService.Called(1, 2, 3)
+ assert.Equal(t, 5, args1.Int(0))
+ assert.Equal(t, 6, args1.Int(1))
+ assert.Equal(t, 7, args1.Int(2))
+
+ args2 := mockedService.Called(4, 5, 6)
+ assert.Equal(t, 5, args2.Int(0))
+ assert.Equal(t, 6, args2.Int(1))
+ assert.Equal(t, 7, args2.Int(2))
+
+}
+
+func Test_Mock_AssertNumberOfCalls(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Called(1, 2, 3)
+ assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1))
+
+ mockedService.Called(1, 2, 3)
+ assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2))
+
+}
+
+func Test_Mock_AssertCalled(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Called(1, 2, 3)
+
+ assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3))
+
+}
+
+func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.
+ On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).
+ Return()
+
+ mockedService.Called(1, "two", []uint8("three"))
+
+ assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8")))
+
+}
+
+func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Called(1, 2, 3)
+
+ tt := new(testing.T)
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3))
+ assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4))
+
+}
+
+func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once()
+ mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once()
+
+ mockedService.Called(1, 2, 3)
+ mockedService.Called(2, 3, 4)
+
+ tt := new(testing.T)
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3))
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4))
+ assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5))
+
+}
+
+func Test_Mock_AssertNotCalled(t *testing.T) {
+
+ var mockedService = new(TestExampleImplementation)
+
+ mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Called(1, 2, 3)
+
+ assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled"))
+
+}
+
+func Test_Mock_IsMethodCallable(t *testing.T) {
+ var mockedService = new(TestExampleImplementation)
+
+ arg := []Call{{Repeatability: 1}, {Repeatability: 2}}
+ arg2 := []Call{{Repeatability: 1}, {Repeatability: 1}}
+ arg3 := []Call{{Repeatability: 1}, {Repeatability: 1}}
+
+ mockedService.On("Test_Mock_IsMethodCallable", arg2).Return(true).Twice()
+
+ assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg))
+ assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2))
+ assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg3))
+
+ mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2)
+ mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2)
+
+ assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2))
+}
+
+func TestIsArgsEqual(t *testing.T) {
+ var expected = Arguments{5, 3, 4, 6, 7, 2}
+ var args = make([]interface{}, 5)
+ for i := 1; i < len(expected); i++ {
+ args[i-1] = expected[i]
+ }
+ args[2] = expected[1]
+ assert.False(t, isArgsEqual(expected, args))
+
+ var arr = make([]interface{}, 6)
+ for i := 0; i < len(expected); i++ {
+ arr[i] = expected[i]
+ }
+ assert.True(t, isArgsEqual(expected, arr))
+}
+
+func Test_Mock_AssertOptional(t *testing.T) {
+ // Optional called
+ var ms1 = new(TestExampleImplementation)
+ ms1.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil)
+ ms1.TheExampleMethod(1, 2, 3)
+
+ tt1 := new(testing.T)
+ assert.Equal(t, true, ms1.AssertExpectations(tt1))
+
+ // Optional not called
+ var ms2 = new(TestExampleImplementation)
+ ms2.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil)
+
+ tt2 := new(testing.T)
+ assert.Equal(t, true, ms2.AssertExpectations(tt2))
+
+ // Non-optional called
+ var ms3 = new(TestExampleImplementation)
+ ms3.On("TheExampleMethod", 1, 2, 3).Return(4, nil)
+ ms3.TheExampleMethod(1, 2, 3)
+
+ tt3 := new(testing.T)
+ assert.Equal(t, true, ms3.AssertExpectations(tt3))
+}
+
+/*
+Arguments helper methods
+*/
+func Test_Arguments_Get(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+
+ assert.Equal(t, "string", args.Get(0).(string))
+ assert.Equal(t, 123, args.Get(1).(int))
+ assert.Equal(t, true, args.Get(2).(bool))
+
+}
+
+func Test_Arguments_Is(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+
+ assert.True(t, args.Is("string", 123, true))
+ assert.False(t, args.Is("wrong", 456, false))
+
+}
+
+func Test_Arguments_Diff(t *testing.T) {
+
+ var args = Arguments([]interface{}{"Hello World", 123, true})
+ var diff string
+ var count int
+ diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
+
+ assert.Equal(t, 2, count)
+ assert.Contains(t, diff, `(int=456) != (int=123)`)
+ assert.Contains(t, diff, `(string=false) != (bool=true)`)
+
+}
+
+func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ var diff string
+ var count int
+ diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
+
+ assert.Equal(t, 3, count)
+ assert.Contains(t, diff, `(string=extra) != (Missing)`)
+
+}
+
+func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ var count int
+ _, count = args.Diff([]interface{}{"string", Anything, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", Anything, true})
+ var count int
+ _, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", AnythingOfType("int"), true})
+ var count int
+ _, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", AnythingOfType("string"), true})
+ var count int
+ var diff string
+ diff, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 1, count)
+ assert.Contains(t, diff, `string != type int - (int=123)`)
+
+}
+
+func Test_Arguments_Diff_WithIsTypeArgument(t *testing.T) {
+ var args = Arguments([]interface{}{"string", IsType(0), true})
+ var count int
+ _, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 0, count)
+}
+
+func Test_Arguments_Diff_WithIsTypeArgument_Failing(t *testing.T) {
+ var args = Arguments([]interface{}{"string", IsType(""), true})
+ var count int
+ var diff string
+ diff, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 1, count)
+ assert.Contains(t, diff, `string != type int - (int=123)`)
+}
+
+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, `(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, `(bool=false) not matched by func(int) bool`)
+
+ diff, count = args.Diff([]interface{}{"string", 123, false})
+ assert.Equal(t, 1, count)
+ assert.Contains(t, diff, `(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})
+
+ assert.True(t, args.Assert(t, "string", 123, true))
+
+}
+
+func Test_Arguments_String_Representation(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ assert.Equal(t, `string,int,bool`, args.String())
+
+}
+
+func Test_Arguments_String(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ assert.Equal(t, "string", args.String(0))
+
+}
+
+func Test_Arguments_Error(t *testing.T) {
+
+ var err = errors.New("An Error")
+ var args = Arguments([]interface{}{"string", 123, true, err})
+ assert.Equal(t, err, args.Error(3))
+
+}
+
+func Test_Arguments_Error_Nil(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true, nil})
+ assert.Equal(t, nil, args.Error(3))
+
+}
+
+func Test_Arguments_Int(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ assert.Equal(t, 123, args.Int(1))
+
+}
+
+func Test_Arguments_Bool(t *testing.T) {
+
+ var args = Arguments([]interface{}{"string", 123, true})
+ assert.Equal(t, true, args.Bool(2))
+
+}
+
+func Test_WaitUntil_Parallel(t *testing.T) {
+
+ // make a test impl object
+ var mockedService = new(TestExampleImplementation)
+
+ ch1 := make(chan time.Time)
+ ch2 := make(chan time.Time)
+
+ mockedService.Mock.On("TheExampleMethod2", true).Return().WaitUntil(ch2).Run(func(args Arguments) {
+ ch1 <- time.Now()
+ })
+
+ mockedService.Mock.On("TheExampleMethod2", false).Return().WaitUntil(ch1)
+
+ // Lock both goroutines on the .WaitUntil method
+ go func() {
+ mockedService.TheExampleMethod2(false)
+ }()
+ go func() {
+ mockedService.TheExampleMethod2(true)
+ }()
+
+ // Allow the first call to execute, so the second one executes afterwards
+ ch2 <- time.Now()
+}
+
+func Test_MockMethodCalled(t *testing.T) {
+ m := new(Mock)
+ m.On("foo", "hello").Return("world")
+
+ retArgs := m.MethodCalled("foo", "hello")
+ require.True(t, len(retArgs) == 1)
+ require.Equal(t, "world", retArgs[0])
+ m.AssertExpectations(t)
+}
+
+func Test_MockMethodCalled_Panic(t *testing.T) {
+ m := new(Mock)
+ m.On("foo", "hello").Panic("world panics")
+
+ require.PanicsWithValue(t, "world panics", func() { m.MethodCalled("foo", "hello") })
+ m.AssertExpectations(t)
+}
+
+// Test to validate fix for racy concurrent call access in MethodCalled()
+func Test_MockReturnAndCalledConcurrent(t *testing.T) {
+ iterations := 1000
+ m := &Mock{}
+ call := m.On("ConcurrencyTestMethod")
+
+ wg := sync.WaitGroup{}
+ wg.Add(2)
+
+ go func() {
+ for i := 0; i < iterations; i++ {
+ call.Return(10)
+ }
+ wg.Done()
+ }()
+ go func() {
+ for i := 0; i < iterations; i++ {
+ ConcurrencyTestMethod(m)
+ }
+ wg.Done()
+ }()
+ wg.Wait()
+}
+
+type timer struct{ Mock }
+
+func (s *timer) GetTime(i int) string {
+ return s.Called(i).Get(0).(string)
+}
+
+func (s *timer) GetTimes(times []int) string {
+ return s.Called(times).Get(0).(string)
+}
+
+type tCustomLogger struct {
+ *testing.T
+ logs []string
+ errs []string
+}
+
+func (tc *tCustomLogger) Logf(format string, args ...interface{}) {
+ tc.T.Logf(format, args...)
+ tc.logs = append(tc.logs, fmt.Sprintf(format, args...))
+}
+
+func (tc *tCustomLogger) Errorf(format string, args ...interface{}) {
+ tc.errs = append(tc.errs, fmt.Sprintf(format, args...))
+}
+
+func (tc *tCustomLogger) FailNow() {}
+
+func TestLoggingAssertExpectations(t *testing.T) {
+ m := new(timer)
+ m.On("GetTime", 0).Return("")
+ tcl := &tCustomLogger{t, []string{}, []string{}}
+
+ AssertExpectationsForObjects(tcl, m, new(TestExampleImplementation))
+
+ require.Equal(t, 1, len(tcl.errs))
+ assert.Regexp(t, regexp.MustCompile("(?s)FAIL: 0 out of 1 expectation\\(s\\) were met.*The code you are testing needs to make 1 more call\\(s\\).*"), tcl.errs[0])
+ require.Equal(t, 2, len(tcl.logs))
+ assert.Regexp(t, regexp.MustCompile("(?s)FAIL:\tGetTime\\(int\\).*"), tcl.logs[0])
+ require.Equal(t, "Expectations didn't match for Mock: *mock.timer", tcl.logs[1])
+}
+
+func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
+ waitDuration := 1
+ total, waitMs := 5, time.Millisecond*time.Duration(waitDuration)
+ aTimer := new(timer)
+ for i := 0; i < total; i++ {
+ aTimer.On("GetTime", i).After(waitMs).Return(fmt.Sprintf("Time%d", i)).Once()
+ }
+ time.Sleep(waitMs)
+ start := time.Now()
+ var results []string
+
+ for i := 0; i < total; i++ {
+ results = append(results, aTimer.GetTime(i))
+ }
+
+ end := time.Now()
+ elapsedTime := end.Sub(start)
+ assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs))
+ assert.Equal(t, total, len(results))
+ for i := range results {
+ assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same")
+ }
+}
+
+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 TestArgumentMatcherToPrintMismatchWithReferenceType(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ matchingExp := regexp.MustCompile(
+ `\s+mock: Unexpected Method Call\s+-*\s+GetTimes\(\[\]int\)\s+0: \[\]int\{1\}\s+The closest call I have is:\s+GetTimes\(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("GetTimes", MatchedBy(func(_ []int) bool { return false })).Return("SomeTime").Once()
+
+ res := m.GetTimes([]int{1})
+ require.Equal(t, "SomeTime", res)
+ m.AssertExpectations(t)
+}
+
+func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod(int,int,int)`, `0: 1\s+1: 1\s+2: 2`, `0: 1\s+1: 1\s+2: 1`, `Diff: 0: PASS: \(int=1\) == \(int=1\)\s+1: PASS: \(int=1\) == \(int=1\)\s+2: FAIL: \(int=2\) != \(int=1\)`))
+ assert.Regexp(t, matchingExp, r)
+ }
+ }()
+
+ m := new(TestExampleImplementation)
+ m.On("TheExampleMethod", 1, 1, 1).Return(1, nil).Once()
+ m.On("TheExampleMethod", 2, 2, 2).Return(2, nil).Once()
+
+ m.TheExampleMethod(1, 1, 2)
+}
+
+func TestClosestCallFavorsFirstMock(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -2,4 \+2,4 @@\s+\(bool\) true,\s+- \(bool\) true,\s+- \(bool\) true\s+\+ \(bool\) false,\s+\+ \(bool\) false\s+}\s+`
+ matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, false, false}`, `0: \[\]bool{true, true, true}`, diffRegExp))
+ assert.Regexp(t, matchingExp, r)
+ }
+ }()
+
+ m := new(TestExampleImplementation)
+ m.On("TheExampleMethod7", []bool{true, true, true}).Return(nil).Once()
+ m.On("TheExampleMethod7", []bool{false, false, false}).Return(nil).Once()
+
+ m.TheExampleMethod7([]bool{true, false, false})
+}
+
+func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -1,4 \+1,4 @@\s+\(\[\]bool\) \(len=3\) {\s+- \(bool\) false,\s+- \(bool\) false,\s+\+ \(bool\) true,\s+\+ \(bool\) true,\s+\(bool\) false\s+`
+ matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, true, false}`, `0: \[\]bool{false, false, false}`, diffRegExp))
+ assert.Regexp(t, matchingExp, r)
+ }
+ }()
+
+ m := new(TestExampleImplementation)
+ m.On("TheExampleMethod7", []bool{true, true, true}).Return(nil).Once()
+ m.On("TheExampleMethod7", []bool{false, false, false}).Return(nil).Once()
+
+ m.TheExampleMethod7([]bool{true, true, true})
+
+ // Since the first mocked call has already been used, it now has no repeatability,
+ // thus the second mock should be shown as the closest match
+ m.TheExampleMethod7([]bool{true, true, false})
+}
+
+func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "0: 1", "0: 999", `Diff: 0: FAIL: \(int=1\) != \(int=999\)`))
+ assert.Regexp(t, matchingExp, r)
+ }
+ }()
+
+ m := new(timer)
+ m.On("GetTime", 999).Return("SomeTime").Once()
+
+ _ = m.GetTime(1)
+}
+
+func Test_isBetterMatchThanReturnsFalseIfCandidateCallIsNil(t *testing.T) {
+ assert.False(t, matchCandidate{}.isBetterMatchThan(matchCandidate{}))
+}
+
+func Test_isBetterMatchThanReturnsTrueIfOtherCandidateCallIsNil(t *testing.T) {
+ assert.True(t, matchCandidate{call: &Call{}}.isBetterMatchThan(matchCandidate{}))
+}
+
+func Test_isBetterMatchThanReturnsFalseIfDiffCountIsGreaterThanOther(t *testing.T) {
+ assert.False(t, matchCandidate{call: &Call{}, diffCount: 2}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 1}))
+}
+
+func Test_isBetterMatchThanReturnsTrueIfDiffCountIsLessThanOther(t *testing.T) {
+ assert.True(t, matchCandidate{call: &Call{}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 2}))
+}
+
+func Test_isBetterMatchThanReturnsTrueIfRepeatabilityIsGreaterThanOther(t *testing.T) {
+ assert.True(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: -1}, diffCount: 1}))
+}
+
+func Test_isBetterMatchThanReturnsFalseIfRepeatabilityIsLessThanOrEqualToOther(t *testing.T) {
+ assert.False(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: 1}, diffCount: 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+%s\s+The closest call I have is:\s+%s\s+%s\s+%s`,
+ rMethod, calledArg, rMethod, expectedArg, diff)
+}
+
+//go:noinline
+func ConcurrencyTestMethod(m *Mock) {
+ m.Called()
+}
+
+func TestConcurrentArgumentRead(t *testing.T) {
+ methodUnderTest := func(c caller, u user) {
+ go u.Use(c)
+ c.Call()
+ }
+
+ c := &mockCaller{}
+ defer c.AssertExpectations(t)
+
+ u := &mockUser{}
+ defer u.AssertExpectations(t)
+
+ done := make(chan struct{})
+
+ c.On("Call").Return().Once()
+ u.On("Use", c).Return().Once().Run(func(args Arguments) { close(done) })
+
+ methodUnderTest(c, u)
+ <-done // wait until Use is called or assertions will fail
+}
+
+type caller interface {
+ Call()
+}
+
+type mockCaller struct{ Mock }
+
+func (m *mockCaller) Call() { m.Called() }
+
+type user interface {
+ Use(caller)
+}
+
+type mockUser struct{ Mock }
+
+func (m *mockUser) Use(c caller) { m.Called(c) }
diff --git a/vendor/github.com/stretchr/testify/mock/ya.make b/vendor/github.com/stretchr/testify/mock/ya.make
new file mode 100644
index 0000000000..9adef5df41
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/mock/ya.make
@@ -0,0 +1,19 @@
+GO_LIBRARY()
+
+LICENSE(MIT)
+
+GO_SKIP_TESTS(
+ Test_Mock_Chained_On
+ Test_Mock_Chained_UnsetOnlyUnsetsLastCall
+)
+
+SRCS(
+ doc.go
+ mock.go
+)
+
+GO_TEST_SRCS(mock_test.go)
+
+END()
+
+RECURSE(gotest)