Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 1.8 with Mockito 1.9.5 gives compile errors

Tags:

java

mockito

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?

like image 648
Juergen Avatar asked Jul 10 '14 11:07

Juergen


2 Answers

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 ?

like image 191
gontard Avatar answered Sep 18 '22 21:09

gontard


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(...)
like image 32
Andrew Lutsenko Avatar answered Sep 19 '22 21:09

Andrew Lutsenko