Mockito: doReturn vs thenReturn
In Mockito, you can specify what to return when a method is called. That makes unit testing easier because you don’t have to change existing classes. Mockito supports two ways to do it: when-thenReturn
and doReturn-when
. In most cases, when-thenReturn
is used and has better readability.
However, sometimes you need to consider using doReturn-when
because there are different behaviors.
No type safety
The parameter of doReturn
is Object
unlike thenReturn
. So, there is no type checking in the compile time. When the type is mismatched in the runtime, there would be an WrongTypeOfReturnValue
execption.
This is the main reason why when-thenReturn
is a better option if possible.
No side effect
Although there is no type safety, the advantage of doReturn-when
is no side effect. In Mockito, a side effect happens to the real method invocation. To understand this, you need to know when a real method invocation happens.
Generally, you first need to create a mock object with Mockito.mock
before specifying a return value. When you call a method of the mock object, it returns a specified value but it doesn’t do anything you defined in the class. There is no side effect so when-thenReturn
and doReturn-when
acts almost the same except when-thenReturn
has a type safety.
The difference comes when you create a spy with Mockito.spy
. A spied object is linked to an actual object. So, there is a real method invocation when you call a method. This is valid even for when you do when-thenReturn
. This is due to a parameter of when
and it contains a way to invoke a method. e.g. user.getName()
. In contrast, a parameter of when
is only user
when you use doReturn-when
.
A side effect doesn’t happen always but here are the usual cases:
- A method throws an exception with precondition checking.
- A method does what you don’t want while unit testing. For example, network or disk access.
For example, List#get()
throws an exception if the list is smaller. doReturn
can specify a value without having an exception.
Another example is to change a class behavior for unit testing. AccountService
is a target to test so you cannot mock it. With Mocktio.spy
and doReturn
(doNothing
is for void
return type), you can do unit testing without network access.
If there is no side effect, you can still use
when-thenReturn
for a spied object.
Conclusion
You can use doReturn-when
to specify a return value on a spied object without making a side effect. It is useful but should be used rarely. The more you have a better pattern such as MVP, MVVM and dependency injection, the less chance you need to use Mockito.spy
. Then, you can use more type safe and readable Mockito.mock
.