Hey guys! After our previous blog on difference between thenReturn and thenAnswer mockito methods, we are back with yet another interesting blog on Mockito. Here, we shall discuss “How to Mock Void method with Mockito”. Let’s get started!

When writing code, there is always at least one method that returns ‘void’, and at some point in time we need to mock ‘void’ method. So how do we go about it? Let us together figure this out in the following blog using mockito.

Mockito is one of the most famous mocking framework used for writing unit tests. If you are new to mocking you can know more at mockito website.

In this blog we will cover,

Why we need to mock void method?

Let’s assume we have a method. In this method we call another void method. Now, when you want to write test case for this method, how can we test that the void method was called? Also, if the correct parameters were passed to void method?
In this case mockito comes to our rescue.

Let’s take an example, we have a UserService class. In this class we have a updateName() method.

public UserService{
    ...
   public void updateName(Long id, String name){
      userRepository.updateName(id, name);
   }
}

Now, we want to write unit test for UserService class and mock userRepository.
But the only thing we need to verify in this test case is that updateName() method from userRepository is called with correct set of parameters.
For this purpose we need to mock updateName() method, capture the arguments and verify the arguments.

One of the most important point to note here is that, we can not just mock void method using when-then mechanism of mockito. Because, when() method of mockito works with return value and does not work when method is void.

How to mock void method in mockito?

In Mockito we can use different methods to call real method or mock void method. We can use one of the options as per requirements

  1. doNothing() : Completely ignore the calling of void method, this is default behavior
  2. doAnswer() : Perform some run time or complex operations when void method is called
  3. doThrow() : Throw exception when mocked void method is called
  4. doCallRealMethod() : Do not mock and call real method

1) Using doNothing()

If we just want to completely ignore the void method call, we can use doNothing().

In mocking, for every method of mocked object doNothing is the default behavior. Hence, if you don’t want to verify parameters, use of doNothing is completely optional. Following all codes perform similar behavior,

Example using doNothing() for void method

@Test
public void testUpdateNameWithDoNothingVerifyRepositoryCall() {
   doNothing().when(mockedUserRepository).updateName(anyLong(),anyString());

   userService.updateName(1L,"void mock test");
	
   verify(mockedUserRepository, times(1)).updateName(1L,"void mock test");
}

Without using doNothing() for void method

@Test
public void testUpdateNameWithOutDoNothingVerifyRepositoryCall() {

   userService.updateName(1L,"void mock test");
	
   verify(mockedUserRepository, times(1)).updateName(1L,"void mock test");
}

Example of argument capture using doNothing()

We can do different things with argument capture. Here, we will just verify the captured value

@Test
public void testUpdateNameUsingArgumentCaptor() {

   ArgumentCaptor<Long> idCapture = ArgumentCaptor.forClass(Long.class);
   ArgumentCaptor<String> nameCapture = ArgumentCaptor.forClass(String.class);
   doNothing().when(mockedUserRepository).updateName(idCapture.capture(),nameCapture.capture());
 
   userService.updateName(1L,"void mock test");
	
   assertEquals(1L, idCapture.getValue());
   assertEquals("void mock test", nameCapture.getValue());
}

2) Using doAnswer() for void method

If we do not want to call real method, however need to perform some runtime operation doAnswer is used.

Let’s take an example of doAnswer where we will print and verify the argument using doAnswer

@Test
public void testUpdateNameUsingDoAnswer() {
   doAnswer(invocation -> {
      long id = invocation.getArgument(0);
      String name = invocation.getArgument(1);
      System.out.println("called for id: "+id+" and name: "+name);

      assertEquals(1L, id);
      assertEquals("void mock test", name);

      return null;
}).when(mockedUserRepository).updateName(anyLong(),anyString());

   userService.updateName(1L,"void mock test");
   verify(mockedUserRepository, times(1)).updateName(1L,"void mock test");
}

3) Throw exception using doThrow()

If we want to throw an exception when method is called, we can use doThrow() method of mockito.

Let’s take an example where we will throw InvalidParamException when updateName() method is called with null id.

@Test(expected = InvalidParamException.class)
public void testUpdateNameThrowExceptionWhenIdNull() {
   doThrow(new InvalidParamException())
      .when(mockedUserRepository).updateName(null,anyString();
   userService.updateName(null,"void mock test");
}

4) Real method call using doCallRealMethod()

Sometimes it is necessary to call the real method from mocked object, in such case we need to use doCallRealMethod(), because doNothig() is the default behavior.

In the following example real method from userRepository will be called even though it is a mocked object.

@Test
public void testUpdateNameCallRealRepositoryMethod() {

   doCallRealMethod().when(mockedUserRepository).updateName(anyLong(), anyString());
 
   userService.updateName(1L,"calling real method");
 
   verify(mockedUserRepository, times(1)).add(1L,"calling real method");
}

Fast track reading

Reference:

Related Topics:

When it comes to writing test cases for code, Mockito is one of the most common choices of developers. Then we face the question, how to use thenReturn() and thenAnswer() methods of Mockito? If you are facing this also, don’t worry every one faces or has faced this question and we are here to solve it!! So, get set go…

Mockito is one of the most famous mocking framework for testing. Let us assume you already know about mockito. If not you can visit official mockito website before we proceed.

In Mockito insead of calling real method you can specify what to return or do when the method is called. This is called as the “Mocking”.
There are different ways to specify mocked behavior. The most common ways are using thenReturn() and thenAnswer() methods.

Most of the times thenReturn() is used(which is fine) but some times we need to use thenAnswer().

When we should use thenReturn and when thenAnswer?

The simplest answer is – if you need fixed return value on method call then we should use thenReturn(…)
If you need to perform some operation or the value need to be computed at run time then we should use thenAnswer(…)

Let’s look at the examples

Let’s assume we need to return string value “Mockito” on getName() method call.

Mockito.when(mock.getName() ).thenReturn(“Mockito”)

If we need to return system time when we call getCurrentTime method we need

Mockito.when (mock.getCurrentTime() ).thenAnswer(I -> new Date() );

Now let’s get into detail

Method thenReturn() needs a fixed object which will be returned when we call the method.
We can pass any type of object or value, the same value will be returned on method call.

Syntax: OngoingStubbing<T> thenReturn(T value);

Method thenAnswer needs the object of class implementing interface org.mockito.stubbing.Answer.
Answer is the functional interface having method answer(..)
The method answer() will be invoked when we call mocked method from mocked object.
We can use java 8 lambda feature for implementation of answer method.

Syntax: OngoingStubbing<T> thenAnswer(Answer<?> answer);

Basic difference between both is that thenRetun() will always return the same object.

Method thenAnswer will call the method from object every time we invoke the mocked method.

We can also pass function to thenRetun() for defining return value.
There can be 2 scenarios when we use thenAnswer or thenRetun with function.

  1. If function has fix return value, then there will be no difference in the result
    eg. thenReturn(getUserName() );
    And
    thenAnswer(I -> getUserName() ); will function similar
  2. If the return value is computed at run time depending on some parameters the there can be the different results
    eg. thenReturn(getCurrentTime() );
    And
    thenAnswer(I -> getCurrentTime() );

(I) When function returns fixed value

Let’s look at the example below, we have a method getName() to test in user class.
We will create a UserTest class for testing. Then we will mock getName() method.

Public class User { 
  public String getName() {
    return this.name;
  }
} 

 // This is the test class which will test the User class
public class UserTest {

  private String dummyName() {
    System.out.println(" #dummyName called");
    return "Java"; 
 }

@Test
public void thenReturnTest() throws Exception { 
  Tester mock = Mockito.mock(User.class); 
  
  System.out.println("------ Using: thenReturn------ "); 
  Mockito.when(mock.getName()).thenReturn(dummyName());
  
  System.out.println(" -- method calls");   
  System.out.println("Call.1 : " + mock.getName()); 
  System.out.println("Call.2 : " + mock.getName());  
  } 
  
@Test 
public void thenAnswerTest() throws Exception { 
  Tester mock = Mockito.mock(User.class); 

  System.out.println("------ Using: thenAnswer------ "); 
  Mockito.when(mock.getName()).thenAnswer(i -> dummyName()); 

  System.out.println(" -- method calls"); 
  System.out.println("Call.1 : " + mock.getName()); 
  System.out.println("Call.2 : " + mock.getName());
  } 
} 

// OUTPUT:

—— Using: thenReturn——
— #dummyName called
— method calls
Call.1 : Java
Call.2 : Java
—— Using: thenAnswer——
— method calls
— #dummyName called
Call.1 : Java
— #dummyName called
Call.2 : Java

In the above example, we can see that getName() method returns same value in both the cases. However, the printed messages are different.
In case of thenRetun() use dummyName() method was executed before the actual call.

This is because as discussed above thenReturn() needs value hence at the time of initialization it is executed and returned value is used.

Also #dummyName called is printed twice in case of thenAnswer(). This is because every time we call mocked method, the function is executed.

(II) Return value is computed at run time

Let’s look at the example below, we have a method getTime() to test in user class.
We will create a UserTest class for testing. Then will mock getTime() method.

Public class User { 
  public String getTime() {
    return this.time;
  }
} 

public class UserTest {

  private String now() {
    Calendar now = Calendar.getInstance();
    return now.get(Calendar.MINUTE) + " : " + now.get(Calendar.SECOND);
  }
  private String dummyGetTime() {
    System.out.println(" #getTime called");
    return now();
  }
  
@Test 
public void thenReturnTest() throws Exception { 
  Tester mock = Mockito.mock(User.class); 
 
  System.out.println("------ Using: thenReturn------ "); 
  Mockito.when(mock.getTime()).thenReturn(dummyGetTime()); 
  
  System.out.println(" -- method calls");
  System.out.println("Call.1> " + mock.getTime()+ " called at - " +now);

  TimeUnit.SECONDS.sleep(5); 
  System.out.println("Call.2> " + mock.getTime()+ " called at - " +now);
  } 
  
@Test 
public void thenAnswerTest() throws Exception {
  Tester mock = Mockito.mock(User.class); 

  System.out.println("------ Using: thenAnswer------ ");
  Mockito.when(mock.getTime()).thenAnswer(i -> dummyGetTime());
  
  System.out.println(" -- method calls"); 
  System.out.println("Call.1> " + mock.getTime()+ " called at : " +now);

  TimeUnit.SECONDS.sleep(5); 
  System.out.println("Call.2> " + mock.getTime()+ " called at : " +now);
  } 
} 

// OUTPUT: >

—— Using: thenReturn——
— #getTime called
— method calls
Call.1> 4 : 22 called at- 4 : 22
Call.2> 4 : 22 called at- 4 : 27
—— Using: thenAnswer——
— method calls
— #getTime called
Call.1> 4 : 22 called at- 4 : 22
— #getTime called
Call.2> 4 : 27 called at- 4 : 27

In the above example, we can see that getTime() method returns different values in case of thenAnswer() but same value in case of thenRetun().
In case of thenRetun() the value is calculated from now() method i.e. 4:22. This value is used in thenReturn() method every time getTime() function is called.

In case of thenAnswer(), every time we call mocked method getTime(), now() method is also called and returns the new value.

Performance impact

If the method returns simple fixed value we may not see any performance difference. However, if the method has database or network calls, there could be big performance difference.
If value is fixed then we should preferably use thenReturn() as this will only execute once.

Conclusion

We can conclude that the thenReturn() always returns same value whereas thenAnswer() returns the real time computed value.

Fast track reading