Unset
removes all expected calls that satisfy (vs match) arguments in call being unset
#1621
Labels
Unset
removes all expected calls that satisfy (vs match) arguments in call being unset
#1621
Description
When calling
Unset
, any expected call that satisfies the arguments in the call being unset is removed fromExpectedCalls
.For example, in the following scenarios, both the
Anything, Anything
and3,3
calls are removed:Reproduction
Go Playground is timing out on build when
github.com/stretchr/testify/mock
is used (likely due to dependencies downloading), so submitted #1622 with tests to reproduce.Step To Reproduce
Run any/all of the following tests:
Expected behavior
Only the call(s) with the exact matched arguments should be unset/removed.
Ideally only the call that
Unset
is invoked against is removed but the current API is written in a manner that requires aCall
to unset so unless the call is tracked (e.g.,c := mockService.On(....)
),On
must be called first thenUnset
which adds the expectation only to immediately remove it along with any other "matched" expectations. #982 which addedUnset
actually started withUnset
onMock
but then moved it toCall
to supportUnset
on aCall
but possibly it could have considered leavingUnset(methodName string, arguments ...interface{})
on Mock to remove all "matched expectations" and thenUnset
onCall
to remove just that call expectation.At minimum, the docs should be updated to reflect actual behavior (see first item in additional information below).
Actual behavior
All calls that satisfy the arguments are removed
Current Workarounds
ExpectedCalls
- This guidance has been given in several issues (including question / feature-suggestion: built-in way to overwrite / clear ExpectedCalls? #558 which spawnedUnset
being introduced) but has the downside of clearing all expected calls, not just the desired calltestify
that have all this logic already (a newfindExactMatch
is likely needed) and re-creating this is not trivial.Additional Information
On
first (unless the call is tracked) which adds a new call then unsets it (and any others that satisfy) vs. just having aUnset
onMock
that will remove any that match, leading to the 1 to N vs. 0 to 1 behavior. Beyond just not matching the docs, regarding why this is relevant, question / feature-suggestion: built-in way to overwrite / clear ExpectedCalls? #558 covers this well but in short, in a complicated Mock, it is common to setup default expectations and then within an individual test, change those expectations for just that test. For example, if an interface has 10 methods all of which a set of tests use but each test is testing individual portions, aNewMyServiceMock
utility method (aka. builder) could establish defaults which the test than can override/reset/clear. In this case, each test gets a new Mock but the mock is created byNewMyServiceMock
with defaults. Depending on what the defaults are, there is currently no way to change expectations of specific arguments (vs. any expectation that satisfies the arguments).On("TheExampleMethod1", Anything, Anything).Unset()
would remove all expectations fromTheExampleMethod1
that had two parameters) as there isn't an otherwise available API for this currently. This is likely an unintended benefit however, and possibly creating anUnsetAll(methodName string)
would continue to support this for anyone taking advantage of it.Unset
relies on logic similar to MethodCalled and therefore detects any remaining available expectation that satisfies the arguments vs. the exact arguments.On("TheExampleMethod1", Anything, Anything).Unset()
actually adds the expectation and then removes it (along with any others that match).Alternative Solution
If its determined that this is not a bug or even if it is a bug but its determined that changing behavior would not be desirable, alternate approaches could be:
Option 1
UnsetOnly
(or similar) toCall
to remove only the call its invoked againstUnsetAll()
toMock
to remove all expectationsUnsetMethod(methodName string)
toMock
to remove all expectations for a methodUnsetCall(string methodName, methodName string, arguments ...interface{})
toMock
which would behave identical to whatCall.Unset()
does currently but avoids having to callOn
only to then callUnset
UnsetExactCall(string methodName, methodName string, arguments ...interface{})
toMock
to remove all calls that have exact matched arguments** Could combine 3 & 4 to
UnsetCall(exact bool, string methodName, methodName string, arguments ...interface{})
Option 2
findExactCalls
(which would be new and return 0 to N calls) to provide package consumers control over manually manipulatingMock.ExpectedCalls
. This is likely less than ideal but at least would give consumers of package an option to accomplish the desired behaviorRelated Issues
#1511 proposes a
Replace
API which is often whyUnset
is needed. If #1511 were merged currently, it would replace all "matched" expectations which wouldn't necessarily be only one expectationThe text was updated successfully, but these errors were encountered: