Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Final Kotlin class can not be mocked because method "should return Validator"

I am trying to write unit tests for my Javalin.io web application. There are a few references to Mockito being used for mocking the Context objects, which is Javalins way to give the user access to the incoming web requests. I am trying to mock the .header(String) method of the Context class because the unit under test is reading the "Authorization" header and performs a JWT check on it.

My pom contains a recent version of Mockito, which should be able to mock final classes:

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>3.2.0</version>
  <scope>test</scope>
</dependency>

I have enabled the inline mock maker as described in the Mockito documentation by creating the file resources/mockito-extensions/org.mockito.plugins.MockMaker with the content mock-maker-inline.

Now I have a stupid test which mocks a Context object and should return "hello123" whenever the header() method of the context object is called. The following code is part of a real unit test but is enough to cause an exception when running the test:

  @Test
  void stupidTest1() {
    Context context = mock(Context.class);

    String test1 = "hello123";
    when(context.header("Authorization")).thenReturn(test1);
  }

and also tried this:

  @Test
  void stupidTest1() {
    Context context = mock(Context.class);

    String test1 = "hello123";
    given(context.header("Authorization")).willReturn(test1);
  }

Executing this test with mvn test fails with the exception:

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)

Is there something I am doing wrong? One point that is weird is that the test sometimes runs successfully, but fails most of the time, especially when running the mvn test command a few times in a row.

like image 324
j9dy Avatar asked May 14 '20 08:05

j9dy


1 Answers

I could reproduce the issue at my local. It seems there is an issue during classloading and Mockito cannot find the correct method every time. You can change the test as below to make sure it finds the correct header method. It worked at my local.

@Test
public void stupidTest1() {
    Context context = mock(Context.class);
    String test1 = "hello123";
    Validator<String> f = new Validator<String>("hello123","Value");
    when(context.header(test1,String.class)).thenReturn(f);
}
like image 118
Mehmet Sunkur Avatar answered Nov 04 '22 15:11

Mehmet Sunkur