Mockito doReturn: ambiguous reference to overloaded definition - java

I'm trying to port a Scala system to Mockito2. There are a few test cases that use doReturn and now in Mockito 2.18.0 I get this error:
Error:(34, 5) ambiguous reference to overloaded definition,
both method doReturn in object Mockito of type (x$1: Any, x$2: Object*)org.mockito.stubbing.Stubber
and method doReturn in object Mockito of type (x$1: Any)org.mockito.stubbing.Stubber
match argument types (com.twitter.util.Future[Unit])
doReturn(Future.Unit).when(f.adapterSpy).myFunction(userData, Some(offerId), Always)
Looking in Mockito.java, doReturn is really overloaded like that:
public static Stubber doReturn(Object toBeReturned)
public static Stubber doReturn(Object toBeReturned, Object... toBeReturnedNext)
How on Earth is this not always ambiguous? How do I make it compile?
Thanks

As a temporary workaround, you can do the following:
trait MockitoHelper extends MockitoSugar {
def doReturn(toBeReturned: Any): Stubber = {
Mockito.doReturn(toBeReturned, Nil: _*)
}
}
Then have your test mixin this MockitoHelper.

This can also be overcome by using doAnswer instead of doReturn
// no good
doReturn(true).when(foo).bar()
// works
doAnswer(_ => true).when(foo).bar()

There is a ticket in the Scala backlog on it. see https://github.com/scala/bug/issues/4775

This is a bit of self promotion but I just published a library called mockito-scala that solves this issue and many more, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.
Specifically for your problem, you could write this code and it would work out of the box
doReturn(Future.successful(())).when(f.adapterSpy).myFunction(userData, Some(offerId), Always)
I changed the way the future is expressed just because is the correct way to create a completed future of Unit

Related

Java generics from Kotlin when verifying using Mockito?

I'm using Kotlin 1.6.10, Mockito 4.0.0 and Java 8 and I have a Java interface defined like this:
public interface MyInterface {
<D, T extends MyObject<T, D>> T doThings(T myObject);
}
An implementation of this interface is used in a Kotlin application and we have a unit test in which we want to make sure that the doThings method is never called using Mockito. In Java I would just do like this:
verify(myInterfaceInstance, never()).doThings(any());
But if I do this in Kotlin I get a compile-time error:
verify(myInterfaceInstance, never()).doThings(any())
Not enough information to infer type variable D
I understand why this is the case, but I cannot get it to work. In this particular case I really don't care about the generic types, I just want to make sure the doThings is never called. I've tried a lot of different things, for example:
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, Any>>(any())
which fails with:
Type argument is not within its bounds.
Expected:
MyObject<MyObject<*, Any>!, TypeVariable(D)!>!
Found:
MyObject<*, Any!>!
and I've also tried:
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, *>>(any())
and several other permutations which all seem to fail with roughly the same error message.
So my question is, how can I do the equivalent of Java's verify(myInterfaceInstance, never()).doThings(any()); in Kotlin?
This compiles fine, but issues a couple of warnings, you could suppress them via respectful annotation:
#Suppress("TYPE_MISMATCH_WARNING", "UPPER_BOUND_VIOLATED_WARNING")
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, *>?>(any<MyObject<*, *>>())
This is not a Mockito answer, but would the Library Mockk help you? MockK is built specifically for Kotlin so it might have better supports for Generics handling.
The verification would look like:
verify(exactly = 0) { yourClass.doThings(any()) };
https://notwoods.github.io/mockk-guidebook/docs/mocking/verify/
https://mockk.io/#verification-atleast-atmost-or-exactly-times

Mocking method if one argument is raw and other may be from list

I want to test if method was invoked X times with one raw argument and other arguments from list. I found this method:
Mockito.verify(mock,Mockito.times(3)).myMethod(Mockito.eq("lastName"),
Mockito.argThat(Matchers.isOneOf("firstName","name","firstName"))));
However this complains that argThat method needs ArgumentMatcher but Matchers.isOneOf returns org.hamcrest.Matcher
Is there any other way that i could achieve this?
Thanks for help!
This changed in Mockito 2.1.0. On the Mockito web site, there is this migration advice.
All existing custom implementations of ArgumentMatcher will no longer
compile. All locations where hamcrest matchers are passed to argThat()
will no longer compile. There are 2 approaches to fix the problems:
a) Refactor the hamcrest matcher to Mockito matcher: Use implements
ArgumentMatcher instead of extends ArgumentMatcher. Then refactor
describeTo() method into toString() method.
b) Use org.mockito.hamcrest.MockitoHamcrest.argThat() instead of
Mockito.argThat(). Ensure that there is hamcrest dependency on
classpath (Mockito does not depend on hamcrest any more).
What option
is right for you? If you don't mind compile dependency to hamcrest
then option b) is probably right for you. Your choice should not have
big impact and is fully reversible - you can choose different option
in future (and refactor the code)

Eclipse JDT Core - Resolve generic return type for parameterised super method

I am v. inexperienced with the JDT apis, so would be great if someone could help me.
My question is how do I resolve the return type of the test method in the code below?
public interface BaseInterface<T> {
T test();
}
public interface Messages extends BaseInterface<String> {}
I have tried all sorts of searching on google and stackoverflow (ASTParser, visitor, method bindings, etc, but can't seem to find an easy way to get the return type with JDT.
EDIT***
This is related to a bug I created/found a bug in https://github.com/gwt-plugins/gwt-eclipse-plugin/issues/373, and was trying to fix it. My first time working with both JDT and gwt-eclipse plugin code, so it was just a stab, not sure if you can give any advice on it. The whole thing maybe need to be attacked in a slightly different way.
It calls the JavaModelSearch.findMethodInHierarchy first which grabs the IMethod, and passes that down, but then can't figure out the return type of T
You should first find the org.eclipse.jdt.core.dom.ITypeBinding for interface "Messages".
From there you can navigate to getSuperclass() or in your case getInterfaces(). This should grant access to the parameterized type "BaseInterface<String>" (note, that the light-weight JavaModel consisting of IType, IMethod etc. does not support the notion of a parameterized type as needed here).
From the latter binding, asking getDeclaredMethods() should answer the desired method "String test()" with return type "String" indeed.
For further inspiration you may want to look that the internal method org.eclipse.jdt.internal.corext.dom.Bindings.findMethodInHierarchy(ITypeBinding, String, ITypeBinding[]).

How to mock method with arg 'T value'?

I have such method:
<T extends Entity> boolean putObject(T value);
But can`t find out how to mock it using mockito? anyObject() and any() produce error:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
1 matchers expected, 3 recorded.
Mock:
when(service.putObject(any(ProcessingTransaction.class))).thenReturn(true);
How it shold work?
Most likely, you have one or two improperly-formed calls to Mockito methods, somewhere earlier in your test (or even in a previous test). When you call a Mockito method that makes an argument matcher (like any()), the matcher gets added to an internal data structure. It's then removed when it's actually used.
The fact that Mockito found three argument matchers instead of just one suggests that you made some argument matchers but didn't use them. For example, if you use when(...) without thenReturn(), this can happen; but there are lots of other cases too.
If you want help finding exactly what you've done wrong, you need to post more of your test code.

Using Hamcrest matchers with JMock in Groovy

I'm new to Groovy (and to JMock too for that matter) and having some trouble building expectations that use matchers on the parameters of the methods being mocked. When I try to do something like this:
Expectations e = new Expectations();
e.allowing(mockObject).doSomething(Expectations.with(aNonNull(ImmutableCollection.class)))
e.will(returnValue(someResponse))
It causes the following error when building the expectation:
groovy.lang.MissingMethodException: No signature of method: static org.jmock.Expectations.with() is applicable for argument types: (org.hamcrest.core.IsNot) values: [not null]
Possible solutions: with(boolean), with(org.hamcrest.Matcher), with(byte), with(org.hamcrest.Matcher), with(char), with(org.hamcrest.Matcher)
aNonNull returns Matcher<T> (org.hamcrest.core.IsNot implements Matcher<T>) and there is an Expectations.with method that takes a Matcher so I'm not sure why Groovy is trying to find a version of with that takes the concrete class rather than the interface specified by aNonNull. I've also tried casting the return value of aNonNull to both Matcher and Matcher<T> without any change in the error. I'm not sure if there's something about the generics that's confusing Groovy or what else to check.
According to the JavaDoc, org.jmock.Expectations.with() is an instance rather than a static method. That's why you get an error.
By the way, testing/mocking frameworks built specifically for Groovy will make your life a lot easier (even when testing Java code). For example, the same expectation looks like this in Spock (http://spockframework.org):
mockObject.doSomething(_ as ImmutableCollection) >> someResponse
Another Groovy mocking framework to be aware of is GMock (http://code.google.com/p/gmock/).

Categories

Resources