Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verifying method invocation for methods with default parameters can fail unexpectedly #270

Open
george-hawkins opened this issue Jul 17, 2018 · 0 comments

Comments

@george-hawkins
Copy link

george-hawkins commented Jul 17, 2018

Verification of method invocations can fail in a non-obvious way if the method takes default arguments, e.g.:

val foo = mock<Foo>()
foo.beta(4)
verify(foo).beta()

Here we're trying to verify that beta() was called but it mysteriously fails, complaining about a different method altogether:

Wanted but not invoked:
foo.alpha();
-> at ...

On investigation, it's fairly clear why this happens - verify basically just primes things to look for the next method invoked on the mock that was passed to it. Above it seems obvious that this is beta() but the definition of Foo is:

interface Foo {
    fun alpha(): Int
    fun beta(s: Int = alpha())
}

I.e. calling beta() actually always results in alpha() being called on the mock first and hence the verification error referring to alpha().

@nhaarman has already pointed out that the solution to this is to prevent alpha() getting called by providing an argument:

verify(foo).beta(any())

So #174 already covered this but was closed due to lack of activity. Sorry to reopen the issue but the current behavior really is very confusing (I completely understand that this is a result of the interplay between Kotlin's default argument behavior and Mockito and not an issue introduced by mockito-kotlin).

At the moment verify(...) returns its argument, so one can't tell the difference between alpha() being called, to provide an argument, and beta() being called on the thing returned by verify(...). Perhaps it might be possible for verify(...) to wrap the thing it returns so the system can tell the difference between a method being called on that and a method being called on the original mock?

I guess there's already ticket against Mockito itself relating to this as one can get this confusing behavior in Java too? E.g. it doesn't seem obvious that the following shouldn't work in Java either:

verify(foo).beta(foo.alpha())

In Kotlin the issue becomes more pressing as you can't immediately see that anything is happening to foo between verify(...) returning and beta(...) being invoked. So something that's an inconvenience in Java becomes really non-obvious in Kotlin.

@george-hawkins george-hawkins changed the title Verifying method invokation for methods with default parameters can fail unexpectedly Verifying method invocation for methods with default parameters can fail unexpectedly Feb 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant