Skip to content

Commit

Permalink
mock: clear call from NotBefore expectations on Unset()
Browse files Browse the repository at this point in the history
  • Loading branch information
st3penta committed Mar 8, 2024
1 parent 632a260 commit f6aceb7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
20 changes: 20 additions & 0 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ type Call struct {

// Calls which must be satisfied before this call can be
requires []*Call

// Calls that depend on this call to be satisfied so succeed
requiredBy []*Call
}

func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
Expand Down Expand Up @@ -242,6 +245,21 @@ func (c *Call) Unset() *Call {
// trim slice up to last copied index
c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index]

// in-place filter slice for dependent calls to be cleaned - iterate from 0'th to last skipping unnecessary ones
for _, dependentCall := range c.requiredBy {
var index int
for _, requiredByDependent := range dependentCall.requires {
if requiredByDependent == c {
// Remove from the required calls of the dependent call
continue
}
dependentCall.requires[index] = requiredByDependent
index++
}
dependentCall.requires = dependentCall.requires[:index]
}
c.requiredBy = []*Call{}

if !foundMatchingCall {
unlockOnce.Do(c.unlock)
c.Parent.fail("\n\nmock: Could not find expected call\n-----------------------------\n\n%s\n\n",
Expand All @@ -267,6 +285,8 @@ func (c *Call) NotBefore(calls ...*Call) *Call {
if call.Parent == nil {
panic("not before calls must be created with Mock.On()")
}

call.requiredBy = append(call.requiredBy, c)
}

c.requires = append(c.requires, calls...)
Expand Down
35 changes: 35 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,41 @@ func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) {
assert.Equal(t, 0, len(mockedService.ExpectedCalls))
}

func Test_Mock_UnsetOfCallRequiredByNotBefore(t *testing.T) {
// make a test impl object
var mockedServiceA = new(TestExampleImplementation)
var mockedServiceB = new(TestExampleImplementation)
var mockedServiceC = new(TestExampleImplementation)

mock1 := mockedServiceA.
On("TheExampleMethod", 1, 1, 1).
Return(1).
Once()

mock2 := mockedServiceB.
On("TheExampleMethod", 2, 2, 2).
Return(2).
NotBefore(mock1)

mock3 := mockedServiceC.
On("TheExampleMethod", 3, 3, 3).
Return(3).
NotBefore(mock1).
NotBefore(mock2)

assert.Equal(t, 2, len(mock1.requiredBy))
assert.Equal(t, 1, len(mock2.requires))
assert.Equal(t, 1, len(mock2.requiredBy))
assert.Equal(t, 2, len(mock3.requires))

mock1.Unset()

assert.Equal(t, 0, len(mock1.requiredBy))
assert.Equal(t, 0, len(mock2.requires))
assert.Equal(t, 1, len(mock2.requiredBy))
assert.Equal(t, 1, len(mock3.requires))
}

func Test_Mock_UnsetByOnMethodSpec(t *testing.T) {
// make a test impl object
var mockedService = new(TestExampleImplementation)
Expand Down
30 changes: 30 additions & 0 deletions tests/test_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package kata_test

import (
"testing"

"github.com/stretchr/testify/mock"
)

type myMock struct {
mock.Mock
}

func (m *myMock) Do() {
m.Called()
}

func (m *myMock) Dont() {
m.Called()
}

func TestIfy(t *testing.T) {
m := myMock{}
m.Test(t)
defer m.AssertExpectations(t)
call1 := m.On("Dont").Return().Once()
m.On("Do").Return().Once().NotBefore(call1)
call1.Unset()

m.Do()
}

0 comments on commit f6aceb7

Please sign in to comment.