After switching to Java 1.8. JDK some of my test classes fail to compile. Example of implementation class:
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
public class ImplClass {
public <T> Future<T> executeTask(final Callable<T> task) {
return null;
}
}
And here is the test class with Mockito:
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.concurrent.Callable;
import org.junit.Before;
public class TestClass {
private ImplClass implClassMock;
@Before
public void setUp() {
implClassMock = mock(ImplClass.class);
when(implClassMock.executeTask(any(Callable.class))).thenReturn(null);
}
}
I get the error message: The method executeTask(Callable<T>) in the type ImplClass is not applicable for the arguments (Callable)
Switching back to java compiler 1.7 everything is fine.
Any idea how to resolve this issue?
Since java 8, the compiler type inference have been greatly improved.
Now you could remove the class parameter from the matcher without any compilation warning:
when(implClassMock.executeTask(any())).thenReturn(null);
Note: i have the same compiler failure but only with eclipse. A bug may be ?
Looks like this is caused by javac being more flexible than what JLS requires. Eclipse compiler with compliance level of 1.8 is more strict: https://bugs.eclipse.org/bugs/show_bug.cgi?id=430987
The answer by @gontard works in most cases but if the method that you are stubbing has overrides with different parameter types javac will get confused. For example ExecutorService.submit() takes both Callable and Runnable as parameters, you can't mock it with when(executor.submit(any())).then(...) as it is ambiguous. But explicitly parametrizing the type like this will keep both eclipse and javac compilers happy:
when(executor.<Object>submit(any(Callable.class)).then(...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With