Mockito-inline fails to choose correct method to mock for Kotlin classes with "reified" methods in Java tests
See original GitHub issueHi,
I am running into a Mockito (mockito-inline) problem when mocking a final Kotlin class in Java.
The method that I want to mock: fun header(header: String): String? = req.getHeader(header)
The method that Mockito is choosing in a random way on execution of the test… which is causing an exception: inline fun <reified T : Any> header(header: String) = header(header, T::class.java)
My way to mock the method is like this, see entire test method below:
when(context.header("Authorization")).thenReturn(test1);
Because Mockito is choosing the method with return type Validator
instead of the method with return type String
, my tests throw an exception.
The exception that occur in my tests in a random amount of the test runs, i.e. sometimes my test works and sometimes the wrong method is chosen:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
String cannot be returned by header()
header() should return Validator
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
at my.package.stupidTest1(JavalinTest.java:28)
Can someone explain why Mockito is choosing different methods in each test run? As far as I know, reified
Kotlin methods should be hidden for Java applications and thus Mockito is not working correctly in this manner?
There have been several people that reproduced this issue, please see https://github.com/tipsy/javalin/issues/979
To reproduce:
- Create a Java maven project with JDK compiler source/target value 1.8 in the maven
<properties>
element
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
- Add mockito dependency
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
- Add Javalin dependency
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>3.8.0</version>
</dependency>
- Create the file
resources/mockito-extensions/org.mockito.plugins.MockMaker
with contentmock-maker-inline
so that final Kotlin classes can be mocked - Create a test class that contains only a single method
@Test
void stupidTest1() {
Context context = mock(Context.class);
String test1 = "hello123";
when(context.header("Authorization")).thenReturn(test1);
}
- Run the test
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
I assume we would need to include the return type in the method location processor. In Java, the return type is not part of the unique signature. This is an incompatibility of Mockito with Kotlin, we would probably need a project like mockito-scala for Kotlin to address this.
You’d probably have a similar problem to interact with this Kotlin class from Java.
For Kotlin projects, we now recommend
mockito-kotlin
: https://github.com/mockito/mockito-kotlin If you can still reproduce this issue, please open an issue over there and we can investigate further.