Allow partial mixing of concrete values with matchers
See original GitHub issueI’m pretty sure we’re all familiar with the dreadful message “Invalid use of argument matchers” which is caused (most of the time) due to mixing of concrete values and matchers. After using Mockito for several years, I gotta say that this is one of the most annoying drawbacks of the framework.
Recently I’ve been getting more and more into the code of the framework, and started wondering why this restriction is there in the first place. I looked it up, and found this thread on the Google mailing list, in which a guy named Brice (@bric3 ?) explains the reasoning behind this in a fairly simple manner.
In short, the matchers cannot be passed to the mock invocation, since they have a different type than that of the arguments. The way Mockito is handling this is by “registering” the matchers prior to the invocation on a local-thread stack, which the mock-handler later inspects upon the method invocation. When only matchers are used, it is easy to match each matcher to a parameter of the method–by simply matching the stack to the parameter list–but when concrete values are mixed in, this becomes ambiguous.
I would like to suggest a middle-ground solution that will probably cover (at least) 80% of the cases - How about assuming that each null
argument a method is invoked with is supposed to correspond to a matcher, while the rest will be treated as concrete values? This way, only cases where null
is passed “concretely” alongside matchers will be invalid. For example:
when(myMock.foo(any(), null)) // invalid
when(myMock.foo(any(), "1")) // valid
There would also be a problem with primitive types, as matchers cannot be passed to the method as null
s, but in this case they could be passed as default values and then an invocation will be considered invalid if the number of default primitive values passed to the method exceeds the number of matchers of said primitive type on the stack.
Thoughts?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:11
- Comments:15 (11 by maintainers)
Top GitHub Comments
@TimvdLippe @bric3 @szpak @mockitoguy @mockitocore
What do you guys think of a limited support for mixed values/matchers? There is a good chance that Mockito can support mixing for more than 90% of all method calls (just a pessimistic guess). The famous “Invalid use of argument matchers” can become a corner case, were users are still forced to apply matchers everywhere. This would make test code even better / more readable.
I see currently following expansion stages:
eq(..)
,any###()
) using default matcher return values@oleksiyp I came to a similar solution in #828 “Prototype implementation of when syntax for void methods”. Since
when
needs to accept a lambda the Mockito API needs an update, i guess this wont happen in Mockito 2. Introducing when with lambda would be useful to unify the whole stubbing API too.