question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mockito-inline fails to choose correct method to mock for Kotlin classes with "reified" methods in Java tests

See original GitHub issue

Hi,

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:

  1. 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>
  1. Add mockito dependency
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>3.2.0</version>
  <scope>test</scope>
</dependency>
  1. Add Javalin dependency
<dependency>
  <groupId>io.javalin</groupId>
  <artifactId>javalin</artifactId>
  <version>3.8.0</version>
</dependency>
  1. Create the file resources/mockito-extensions/org.mockito.plugins.MockMaker with content mock-maker-inline so that final Kotlin classes can be mocked
  2. 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);
  }
  1. Run the test

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
raphwcommented, Aug 13, 2020

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.

0reactions
TimvdLippecommented, Nov 3, 2021

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mockito when clause not working in kotlin - Stack Overflow
inline fun <reified T> mock(): T = Mockito.mock(T::class.java) ... So even though the class is non-final the method is final and not mocked....
Read more >
Kotlin unit test failing when using generics and Mockito - Support
The test is using this interface: public interface View<T extends ... val view = mock<View<MyModel>>(View<MyModel>::class.java) // testing ...
Read more >
Spring Boot Reference Documentation
Try the How-to documents. They provide solutions to the most common questions. Learn the Spring basics. Spring Boot builds on many other Spring...
Read more >
Mocking Static Methods with Mockito (Java & Kotlin) - rieckpil
Start asking your teammates whether or not you should mock static method calls. It's debatable if this is an absolute no-go or sometimes...
Read more >
Unit testing in Kotlin projects with Mockk vs. Mockito
Mockito and Mockk are written in Java and Kotlin, respectively, ... and idiomatic Kotlin code; Mocking support for final classes and methods ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found