From 2b6b233db81f13bf29bd05c9ec73cab20c992dad Mon Sep 17 00:00:00 2001 From: Ivan Lutsenka Date: Mon, 7 Apr 2025 20:43:10 +0300 Subject: [PATCH 1/2] support func comparison in mocks --- Makefile | 1 + equal.go | 20 ++ equal_test.go | 74 +++++++ tests/func_caller_mock.go | 384 +++++++++++++++++++++++++++++++++ tests/func_caller_mock_test.go | 130 +++++++++++ tests/types.go | 4 + 6 files changed, 613 insertions(+) create mode 100644 equal_test.go create mode 100644 tests/func_caller_mock.go create mode 100644 tests/func_caller_mock_test.go diff --git a/Makefile b/Makefile index a6dd335..134b8bd 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ generate: go run ./cmd/minimock/minimock.go -i ./tests.formatterAlias -o ./tests/formatter_alias_mock.go go run ./cmd/minimock/minimock.go -i ./tests.formatterType -o ./tests/formatter_type_mock.go go run ./cmd/minimock/minimock.go -i ./tests.reader -o ./tests/reader_mock.go -gr + go run ./cmd/minimock/minimock.go -i ./tests.funcCaller -o ./tests/func_caller_mock.go ./bin: mkdir ./bin diff --git a/equal.go b/equal.go index 80e9ecb..a004c40 100644 --- a/equal.go +++ b/equal.go @@ -40,6 +40,10 @@ func Equal(a, b interface{}) bool { continue } + if checkFunctions(aFieldValue, bFieldValue) { + continue + } + if !reflect.DeepEqual(aFieldValue, bFieldValue) { return false } @@ -48,6 +52,10 @@ func Equal(a, b interface{}) bool { return true } + if checkFunctions(a, b) { + return true + } + return reflect.DeepEqual(a, b) } @@ -103,3 +111,15 @@ func unexported(field reflect.Value) interface{} { func unexportedVal(field reflect.Value) reflect.Value { return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem() } + +// checkFunctions returns true +func checkFunctions(a, b interface{}) (differs bool) { + if a == nil || b == nil { + return false + } + if reflect.TypeOf(a).Kind() != reflect.Func || reflect.TypeOf(b).Kind() != reflect.Func { + return false + } + + return reflect.ValueOf(a).UnsafePointer() == reflect.ValueOf(b).UnsafePointer() +} diff --git a/equal_test.go b/equal_test.go new file mode 100644 index 0000000..f26bc38 --- /dev/null +++ b/equal_test.go @@ -0,0 +1,74 @@ +package minimock + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCheckFunctions(t *testing.T) { + t.Parallel() + var ( + validFunc = func() {} + nilFunc func() = nil + ) + + tests := []struct { + name string + a interface{} + b interface{} + want bool + }{{ + name: "one is nil, another is nil func", + a: nil, + b: nilFunc, + want: false, + }, { + name: "arguments are nil", + a: nil, + b: nil, + want: false, + }, { + name: "nil func and nil", + a: nilFunc, + b: nil, + want: false, + }, { + name: "arguments are not functions", + a: 1, + b: "string", + want: false, + }, { + name: "both functions are nil", + a: nilFunc, + b: nilFunc, + want: true, + }, { + name: "a is nil", + a: nilFunc, + b: validFunc, + want: false, + }, { + name: "b is nil", + a: validFunc, + b: nilFunc, + want: false, + }, { + name: "functions are anonymous", + a: func() {}, + b: func() {}, + want: false, + }, { + name: "functions are equal", + a: validFunc, + b: validFunc, + want: true, + }} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + assert.Equal(t, tt.want, checkFunctions(tt.a, tt.b)) + }) + } +} diff --git a/tests/func_caller_mock.go b/tests/func_caller_mock.go new file mode 100644 index 0000000..e1e1229 --- /dev/null +++ b/tests/func_caller_mock.go @@ -0,0 +1,384 @@ +// Code generated by http://github.com/gojuno/minimock (dev). DO NOT EDIT. + +package tests + +//go:generate minimock -i github.com/gojuno/minimock/v3/tests.funcCaller -o func_caller_mock.go -n FuncCallerMock -p tests + +import ( + "sync" + mm_atomic "sync/atomic" + mm_time "time" + + "github.com/gojuno/minimock/v3" +) + +// FuncCallerMock implements funcCaller +type FuncCallerMock struct { + t minimock.Tester + finishOnce sync.Once + + funcCallFunc func(f func()) (i1 int) + funcCallFuncOrigin string + inspectFuncCallFunc func(f func()) + afterCallFuncCounter uint64 + beforeCallFuncCounter uint64 + CallFuncMock mFuncCallerMockCallFunc +} + +// NewFuncCallerMock returns a mock for funcCaller +func NewFuncCallerMock(t minimock.Tester) *FuncCallerMock { + m := &FuncCallerMock{t: t} + + if controller, ok := t.(minimock.MockController); ok { + controller.RegisterMocker(m) + } + + m.CallFuncMock = mFuncCallerMockCallFunc{mock: m} + m.CallFuncMock.callArgs = []*FuncCallerMockCallFuncParams{} + + t.Cleanup(m.MinimockFinish) + + return m +} + +type mFuncCallerMockCallFunc struct { + optional bool + mock *FuncCallerMock + defaultExpectation *FuncCallerMockCallFuncExpectation + expectations []*FuncCallerMockCallFuncExpectation + + callArgs []*FuncCallerMockCallFuncParams + mutex sync.RWMutex + + expectedInvocations uint64 + expectedInvocationsOrigin string +} + +// FuncCallerMockCallFuncExpectation specifies expectation struct of the funcCaller.CallFunc +type FuncCallerMockCallFuncExpectation struct { + mock *FuncCallerMock + params *FuncCallerMockCallFuncParams + paramPtrs *FuncCallerMockCallFuncParamPtrs + expectationOrigins FuncCallerMockCallFuncExpectationOrigins + results *FuncCallerMockCallFuncResults + returnOrigin string + Counter uint64 +} + +// FuncCallerMockCallFuncParams contains parameters of the funcCaller.CallFunc +type FuncCallerMockCallFuncParams struct { + f func() +} + +// FuncCallerMockCallFuncParamPtrs contains pointers to parameters of the funcCaller.CallFunc +type FuncCallerMockCallFuncParamPtrs struct { + f *func() +} + +// FuncCallerMockCallFuncResults contains results of the funcCaller.CallFunc +type FuncCallerMockCallFuncResults struct { + i1 int +} + +// FuncCallerMockCallFuncOrigins contains origins of expectations of the funcCaller.CallFunc +type FuncCallerMockCallFuncExpectationOrigins struct { + origin string + originF string +} + +// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning +// the test will fail minimock's automatic final call check if the mocked method was not called at least once. +// Optional() makes method check to work in '0 or more' mode. +// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to +// catch the problems when the expected method call is totally skipped during test run. +func (mmCallFunc *mFuncCallerMockCallFunc) Optional() *mFuncCallerMockCallFunc { + mmCallFunc.optional = true + return mmCallFunc +} + +// Expect sets up expected params for funcCaller.CallFunc +func (mmCallFunc *mFuncCallerMockCallFunc) Expect(f func()) *mFuncCallerMockCallFunc { + if mmCallFunc.mock.funcCallFunc != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by Set") + } + + if mmCallFunc.defaultExpectation == nil { + mmCallFunc.defaultExpectation = &FuncCallerMockCallFuncExpectation{} + } + + if mmCallFunc.defaultExpectation.paramPtrs != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by ExpectParams functions") + } + + mmCallFunc.defaultExpectation.params = &FuncCallerMockCallFuncParams{f} + mmCallFunc.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) + for _, e := range mmCallFunc.expectations { + if minimock.Equal(e.params, mmCallFunc.defaultExpectation.params) { + mmCallFunc.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmCallFunc.defaultExpectation.params) + } + } + + return mmCallFunc +} + +// ExpectFParam1 sets up expected param f for funcCaller.CallFunc +func (mmCallFunc *mFuncCallerMockCallFunc) ExpectFParam1(f func()) *mFuncCallerMockCallFunc { + if mmCallFunc.mock.funcCallFunc != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by Set") + } + + if mmCallFunc.defaultExpectation == nil { + mmCallFunc.defaultExpectation = &FuncCallerMockCallFuncExpectation{} + } + + if mmCallFunc.defaultExpectation.params != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by Expect") + } + + if mmCallFunc.defaultExpectation.paramPtrs == nil { + mmCallFunc.defaultExpectation.paramPtrs = &FuncCallerMockCallFuncParamPtrs{} + } + mmCallFunc.defaultExpectation.paramPtrs.f = &f + mmCallFunc.defaultExpectation.expectationOrigins.originF = minimock.CallerInfo(1) + + return mmCallFunc +} + +// Inspect accepts an inspector function that has same arguments as the funcCaller.CallFunc +func (mmCallFunc *mFuncCallerMockCallFunc) Inspect(f func(f func())) *mFuncCallerMockCallFunc { + if mmCallFunc.mock.inspectFuncCallFunc != nil { + mmCallFunc.mock.t.Fatalf("Inspect function is already set for FuncCallerMock.CallFunc") + } + + mmCallFunc.mock.inspectFuncCallFunc = f + + return mmCallFunc +} + +// Return sets up results that will be returned by funcCaller.CallFunc +func (mmCallFunc *mFuncCallerMockCallFunc) Return(i1 int) *FuncCallerMock { + if mmCallFunc.mock.funcCallFunc != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by Set") + } + + if mmCallFunc.defaultExpectation == nil { + mmCallFunc.defaultExpectation = &FuncCallerMockCallFuncExpectation{mock: mmCallFunc.mock} + } + mmCallFunc.defaultExpectation.results = &FuncCallerMockCallFuncResults{i1} + mmCallFunc.defaultExpectation.returnOrigin = minimock.CallerInfo(1) + return mmCallFunc.mock +} + +// Set uses given function f to mock the funcCaller.CallFunc method +func (mmCallFunc *mFuncCallerMockCallFunc) Set(f func(f func()) (i1 int)) *FuncCallerMock { + if mmCallFunc.defaultExpectation != nil { + mmCallFunc.mock.t.Fatalf("Default expectation is already set for the funcCaller.CallFunc method") + } + + if len(mmCallFunc.expectations) > 0 { + mmCallFunc.mock.t.Fatalf("Some expectations are already set for the funcCaller.CallFunc method") + } + + mmCallFunc.mock.funcCallFunc = f + mmCallFunc.mock.funcCallFuncOrigin = minimock.CallerInfo(1) + return mmCallFunc.mock +} + +// When sets expectation for the funcCaller.CallFunc which will trigger the result defined by the following +// Then helper +func (mmCallFunc *mFuncCallerMockCallFunc) When(f func()) *FuncCallerMockCallFuncExpectation { + if mmCallFunc.mock.funcCallFunc != nil { + mmCallFunc.mock.t.Fatalf("FuncCallerMock.CallFunc mock is already set by Set") + } + + expectation := &FuncCallerMockCallFuncExpectation{ + mock: mmCallFunc.mock, + params: &FuncCallerMockCallFuncParams{f}, + expectationOrigins: FuncCallerMockCallFuncExpectationOrigins{origin: minimock.CallerInfo(1)}, + } + mmCallFunc.expectations = append(mmCallFunc.expectations, expectation) + return expectation +} + +// Then sets up funcCaller.CallFunc return parameters for the expectation previously defined by the When method +func (e *FuncCallerMockCallFuncExpectation) Then(i1 int) *FuncCallerMock { + e.results = &FuncCallerMockCallFuncResults{i1} + return e.mock +} + +// Times sets number of times funcCaller.CallFunc should be invoked +func (mmCallFunc *mFuncCallerMockCallFunc) Times(n uint64) *mFuncCallerMockCallFunc { + if n == 0 { + mmCallFunc.mock.t.Fatalf("Times of FuncCallerMock.CallFunc mock can not be zero") + } + mm_atomic.StoreUint64(&mmCallFunc.expectedInvocations, n) + mmCallFunc.expectedInvocationsOrigin = minimock.CallerInfo(1) + return mmCallFunc +} + +func (mmCallFunc *mFuncCallerMockCallFunc) invocationsDone() bool { + if len(mmCallFunc.expectations) == 0 && mmCallFunc.defaultExpectation == nil && mmCallFunc.mock.funcCallFunc == nil { + return true + } + + totalInvocations := mm_atomic.LoadUint64(&mmCallFunc.mock.afterCallFuncCounter) + expectedInvocations := mm_atomic.LoadUint64(&mmCallFunc.expectedInvocations) + + return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations) +} + +// CallFunc implements funcCaller +func (mmCallFunc *FuncCallerMock) CallFunc(f func()) (i1 int) { + mm_atomic.AddUint64(&mmCallFunc.beforeCallFuncCounter, 1) + defer mm_atomic.AddUint64(&mmCallFunc.afterCallFuncCounter, 1) + + mmCallFunc.t.Helper() + + if mmCallFunc.inspectFuncCallFunc != nil { + mmCallFunc.inspectFuncCallFunc(f) + } + + mm_params := FuncCallerMockCallFuncParams{f} + + // Record call args + mmCallFunc.CallFuncMock.mutex.Lock() + mmCallFunc.CallFuncMock.callArgs = append(mmCallFunc.CallFuncMock.callArgs, &mm_params) + mmCallFunc.CallFuncMock.mutex.Unlock() + + for _, e := range mmCallFunc.CallFuncMock.expectations { + if minimock.Equal(*e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.i1 + } + } + + if mmCallFunc.CallFuncMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmCallFunc.CallFuncMock.defaultExpectation.Counter, 1) + mm_want := mmCallFunc.CallFuncMock.defaultExpectation.params + mm_want_ptrs := mmCallFunc.CallFuncMock.defaultExpectation.paramPtrs + + mm_got := FuncCallerMockCallFuncParams{f} + + if mm_want_ptrs != nil { + + if mm_want_ptrs.f != nil && !minimock.Equal(*mm_want_ptrs.f, mm_got.f) { + mmCallFunc.t.Errorf("FuncCallerMock.CallFunc got unexpected parameter f, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmCallFunc.CallFuncMock.defaultExpectation.expectationOrigins.originF, *mm_want_ptrs.f, mm_got.f, minimock.Diff(*mm_want_ptrs.f, mm_got.f)) + } + + } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmCallFunc.t.Errorf("FuncCallerMock.CallFunc got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmCallFunc.CallFuncMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmCallFunc.CallFuncMock.defaultExpectation.results + if mm_results == nil { + mmCallFunc.t.Fatal("No results are set for the FuncCallerMock.CallFunc") + } + return (*mm_results).i1 + } + if mmCallFunc.funcCallFunc != nil { + return mmCallFunc.funcCallFunc(f) + } + mmCallFunc.t.Fatalf("Unexpected call to FuncCallerMock.CallFunc. %v", f) + return +} + +// CallFuncAfterCounter returns a count of finished FuncCallerMock.CallFunc invocations +func (mmCallFunc *FuncCallerMock) CallFuncAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmCallFunc.afterCallFuncCounter) +} + +// CallFuncBeforeCounter returns a count of FuncCallerMock.CallFunc invocations +func (mmCallFunc *FuncCallerMock) CallFuncBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmCallFunc.beforeCallFuncCounter) +} + +// Calls returns a list of arguments used in each call to FuncCallerMock.CallFunc. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmCallFunc *mFuncCallerMockCallFunc) Calls() []*FuncCallerMockCallFuncParams { + mmCallFunc.mutex.RLock() + + argCopy := make([]*FuncCallerMockCallFuncParams, len(mmCallFunc.callArgs)) + copy(argCopy, mmCallFunc.callArgs) + + mmCallFunc.mutex.RUnlock() + + return argCopy +} + +// MinimockCallFuncDone returns true if the count of the CallFunc invocations corresponds +// the number of defined expectations +func (m *FuncCallerMock) MinimockCallFuncDone() bool { + if m.CallFuncMock.optional { + // Optional methods provide '0 or more' call count restriction. + return true + } + + for _, e := range m.CallFuncMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + return m.CallFuncMock.invocationsDone() +} + +// MinimockCallFuncInspect logs each unmet expectation +func (m *FuncCallerMock) MinimockCallFuncInspect() { + for _, e := range m.CallFuncMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to FuncCallerMock.CallFunc at\n%s with params: %#v", e.expectationOrigins.origin, *e.params) + } + } + + afterCallFuncCounter := mm_atomic.LoadUint64(&m.afterCallFuncCounter) + // if default expectation was set then invocations count should be greater than zero + if m.CallFuncMock.defaultExpectation != nil && afterCallFuncCounter < 1 { + if m.CallFuncMock.defaultExpectation.params == nil { + m.t.Errorf("Expected call to FuncCallerMock.CallFunc at\n%s", m.CallFuncMock.defaultExpectation.returnOrigin) + } else { + m.t.Errorf("Expected call to FuncCallerMock.CallFunc at\n%s with params: %#v", m.CallFuncMock.defaultExpectation.expectationOrigins.origin, *m.CallFuncMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcCallFunc != nil && afterCallFuncCounter < 1 { + m.t.Errorf("Expected call to FuncCallerMock.CallFunc at\n%s", m.funcCallFuncOrigin) + } + + if !m.CallFuncMock.invocationsDone() && afterCallFuncCounter > 0 { + m.t.Errorf("Expected %d calls to FuncCallerMock.CallFunc at\n%s but found %d calls", + mm_atomic.LoadUint64(&m.CallFuncMock.expectedInvocations), m.CallFuncMock.expectedInvocationsOrigin, afterCallFuncCounter) + } +} + +// MinimockFinish checks that all mocked methods have been called the expected number of times +func (m *FuncCallerMock) MinimockFinish() { + m.finishOnce.Do(func() { + if !m.minimockDone() { + m.MinimockCallFuncInspect() + } + }) +} + +// MinimockWait waits for all mocked methods to be called the expected number of times +func (m *FuncCallerMock) MinimockWait(timeout mm_time.Duration) { + timeoutCh := mm_time.After(timeout) + for { + if m.minimockDone() { + return + } + select { + case <-timeoutCh: + m.MinimockFinish() + return + case <-mm_time.After(10 * mm_time.Millisecond): + } + } +} + +func (m *FuncCallerMock) minimockDone() bool { + done := true + return done && + m.MinimockCallFuncDone() +} diff --git a/tests/func_caller_mock_test.go b/tests/func_caller_mock_test.go new file mode 100644 index 0000000..a347e21 --- /dev/null +++ b/tests/func_caller_mock_test.go @@ -0,0 +1,130 @@ +package tests + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFuncCallerMock_AcceptsFunc(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + validFunc := func() { _ = 1 } + mock := NewFuncCallerMock(tester) + mock.CallFuncMock.Expect(validFunc).Return(1) + + assert.Equal(t, 1, mock.CallFunc(validFunc)) +} + +func TestFuncCallerMock_ChecksNilFunc(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + var f func() + mock := NewFuncCallerMock(tester) + mock.CallFuncMock.Expect(f).Return(1) + + assert.Equal(t, 1, mock.CallFunc(nil)) +} + +func TestFuncCallerMock_ChecksNil(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + var f func() + mock := NewFuncCallerMock(tester) + mock.CallFuncMock.Expect(nil).Return(1) + + assert.Equal(t, 1, mock.CallFunc(f)) +} + +func TestFuncCallerMock_WhenThen(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + var ( + f1 func() + f2 = func() { _ = 2 } + ) + mock := NewFuncCallerMock(tester) + mock. + CallFuncMock.When(f1).Then(1). + CallFuncMock.When(f2).Then(2) + + assert.Equal(t, 1, mock.CallFunc(f1)) + assert.Equal(t, 2, mock.CallFunc(f2)) +} + +func TestFuncCallerMock_Method(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + mock := NewFuncCallerMock(tester) + + var obj object + mock. + CallFuncMock.When(obj.Method1).Then(1). + CallFuncMock.When(obj.Method2).Then(2) + + assert.Equal(t, 1, mock.CallFunc(obj.Method1)) + assert.Equal(t, 2, mock.CallFunc(obj.Method2)) +} + +func TestFuncCallerMock_SameVTable(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + mock := NewFuncCallerMock(tester) + + var ( + obj1 object + obj2 object + ) + mock.CallFuncMock.Expect(obj1.Method1).Times(2).Return(1) + + assert.Equal(t, 1, mock.CallFunc(obj1.Method1)) + assert.Equal(t, 1, mock.CallFunc(obj2.Method1)) +} + +func TestFuncCallerMock_Closures(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return().ErrorfMock.Return() + + mock := NewFuncCallerMock(tester) + + mock.CallFuncMock.Expect(func() {}).Return(1) + + _ = mock.CallFunc(func() {}) +} + +func TestFuncCallerMock_ClosuresPartial(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return().ErrorfMock.Return() + + mock := NewFuncCallerMock(tester) + + mock.CallFuncMock.ExpectFParam1(func() {}).Return(1) + + _ = mock.CallFunc(func() {}) +} + +func TestFuncCallerMock_Partial(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return() + + mock := NewFuncCallerMock(tester) + + f := func() {} + mock.CallFuncMock.ExpectFParam1(f).Return(1) + + assert.Equal(t, 1, mock.CallFunc(f)) +} + +type object struct{} + +func (o object) Method1() { +} + +func (o object) Method2() { +} diff --git a/tests/types.go b/tests/types.go index 925f1b6..46923bd 100644 --- a/tests/types.go +++ b/tests/types.go @@ -93,4 +93,8 @@ type ( actor interface { Action(firstParam string, secondParam int) (int, error) } + + funcCaller interface { + CallFunc(f func()) int + } ) From ee36290e683a2ba1e856837971fa7e6599174385 Mon Sep 17 00:00:00 2001 From: Ivan Lutsenka Date: Tue, 8 Apr 2025 10:11:01 +0300 Subject: [PATCH 2/2] add more tests for FuncCallerMock --- tests/func_caller_mock_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/func_caller_mock_test.go b/tests/func_caller_mock_test.go index a347e21..fb8131f 100644 --- a/tests/func_caller_mock_test.go +++ b/tests/func_caller_mock_test.go @@ -121,6 +121,29 @@ func TestFuncCallerMock_Partial(t *testing.T) { assert.Equal(t, 1, mock.CallFunc(f)) } +func TestFuncCallerMock_Functions(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return().ErrorfMock.Return() + + mock := NewFuncCallerMock(tester) + + mock.CallFuncMock.Expect(function1).Return(1) + + assert.Equal(t, 1, mock.CallFunc(function1)) + mock.CallFunc(function2) +} + +func TestFuncCallerMock_ClosuresFromFunc(t *testing.T) { + tester := NewTesterMock(t) + tester.CleanupMock.Return().HelperMock.Return().ErrorfMock.Return() + + mock := NewFuncCallerMock(tester) + + mock.CallFuncMock.Expect(newClosure()).Return(1) + + mock.CallFunc(newClosure()) +} + type object struct{} func (o object) Method1() { @@ -128,3 +151,11 @@ func (o object) Method1() { func (o object) Method2() { } + +func function1() {} + +func function2() {} + +func newClosure() func() { + return func() {} +}