Mockito allows you to specify what to return when a method is called on a mocked object. Mockito supports two ways to do it: `when-thenReturn` and `doReturn-when`. In most cases, `when-thenReturn` is used and has better readability.
Below is the example usage for testing our UserService class that has dependency on UserRepository class.
/**
* Test class to show example implementation of when-thenReturn and doReturn-when pattern of Mockito to define return
* types from a mocked method.
*/
class UserServiceReturnOptionsTest {
/**
* This method used when-thenReturn pattern to set return value from a mock object
*/
@Test
void when_then_example() {
// Create a mock object for dependency class
UserRepository mockUserRepository = Mockito.mock(UserRepository.class);
// Add mocked dependency to the class object being tested
UserService userService = new UserService(mockUserRepository);
// Use when-thenReturn format to specify return value for invoked method on mock
Mockito.when(mockUserRepository.findById(100L)).thenReturn(Optional.of(new User(100L)));
// Invoke the method to be tested
Optional<User> userOptional = userService.findById(100L);
// Check return value is as expected
Assertions.assertTrue(userOptional.isPresent());
Assertions.assertEquals(100L, userOptional.get().getId());
}
/**
* This method used doReturn-when pattern to set return value from a mock object
*/
@Test
void doReturn_when_example() {
// Create a mock object for dependency class
UserRepository mockUserRepository = Mockito.mock(UserRepository.class);
// Add mocked dependency to the class object being tested
UserService userService = new UserService(mockUserRepository);
// Use doReturn-when format to specify return value for invoked method on mock
Mockito.doReturn(Optional.of(new User(200L))).when(mockUserRepository).findById(200L);
// Invoke the method to be tested
Optional<User> userOptional = userService.findById(200L);
// Check return value is as expected
Assertions.assertTrue(userOptional.isPresent());
Assertions.assertEquals(200L, userOptional.get().getId());
}
}
In the above example we can see that both the patterns are very similar. But each has its own advantage.
The `when-thenReturn` has the advantage of compile time type checking, whereas `doReturn-when` does not. That means if we specify wrong return type as part of thenReturn() method, we would get a compile time error. Where as a wrong return type in doReturn() will fail only at runtime.
// won't compile
Mockito.when(mockUserRepository.findById(100L)).thenReturn(true);
// Will compile successfully but fail during execution of test.
Mockito.doReturn(true).when(mockUserRepository).findById(200L);
The when() method in `when-thenReturn` ends up invoking the method passed to it i.e. `mockUserRepository.findById(100L)` in example above. This is not a problem when we are using a mock object, since all its method have empty implementation. But this becomes a problem if we use `when-thenReturn` on a spy object created using `Mockito.spy()` method. In that case all the methods retain their actual implementation unless an expectation is defined for them.
The `doReturn-when` pattern is the preferred choice when specifying expectation on a spy object.
// will execute original method, hence can generate error
Mockito.when(mockUserRepository.findById(100L)).thenReturn(Optional.of(new User(200L)));
// Does not execute original method, hence no side effects.
Mockito.doReturn(Optional.of(new User(200L))).when(mockUserRepository).findById(200L);
0 comments:
Post a Comment