314

I am currently in the process of using Mockito to mock my service layer objects in a Spring MVC application in which I want to test my Controller methods. However, as I have been reading on the specifics of Mockito, I have found that the methods doReturn(...).when(...) is equivalent to when(...).thenReturn(...). So, my question is what is the point of having two methods that do the same thing or what is the subtle difference between doReturn(...).when(...) and when(...).thenReturn(...)?

Any help would be appreciated.

blackpanther
  • 10,998
  • 11
  • 48
  • 78
  • 2
    The javadoc has a few cases where `doReturn()` is useful. – Sotirios Delimanolis Dec 03 '13 at 14:39
  • 7
    I think one of the main difference is that doReturn(...).when(..) is an older one and its not that type safe and hence we can use it sometimes when the compiler keeps complaining about casting. The when(..).thenReturn(..) is much better in terms of type safety – user2511882 Dec 03 '13 at 14:45

5 Answers5

326

The two syntaxes for stubbing are roughly equivalent. However, you can always use doReturn/when for stubbing; but there are cases where you can't use when/thenReturn. Stubbing void methods is one such. Others include use with Mockito spies, and stubbing the same method more than once.

One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test.

I strongly recommend only using doReturn/when. There is no point in learning two syntaxes when one will do.

You may wish to refer to my answer at Forming Mockito "grammars" - a more detailed answer to a very closely related question.

Community
  • 1
  • 1
Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • 1
    I completely agree. There is value in consistency. [The Mockito docs suggest otherwise](http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mockito.html#doReturn%28java.lang.Object%29), but they over-emphasize the value of type-safety in `thenReturn()`. – cdunn2001 May 06 '14 at 15:25
  • 33
    I kinda disagree with David. I often run into situations where I return the wrong type when using `doReturn/when` and spend the next few minutes figuring out what went wrong. Compile type type checking becomes extremely useful with `when/thenReturn`. – Saket Feb 15 '16 at 13:14
  • 25
    Just keep in mind that Mockito recommends you use use `when/thenReturn` instead of `doReturn/when`. – CodyEngel Feb 13 '17 at 21:42
  • 5
    @CodyEngel and there is no reason for such a recommendation, other than what I've outlined in my answers here and at http://stackoverflow.com/q/11462697. Several years ago, I discussed this with Brice Dutheil, who is currently acting lead developer of Mockito, and to the best of my memory, he agrees. I will ask him to post a comment here (no guarantee that he'll do so). – Dawood ibn Kareem Feb 13 '17 at 21:50
  • 34
    The [javadoc](https://static.javadoc.io/org.mockito/mockito-core/2.7.11/org/mockito/Mockito.html#doReturn(java.lang.Object)) states that `doReturn/when` is a trade-off. The team does not recommand one way or another but note the `when/then` approach is more intuitive, more readable and offer compile time check, it is the approach that made Mockito popular and easy to use, don't forget that when the code base is shared by various skillset in your team ; yet it has drawbacks regarding spies and void methods. – bric3 Feb 24 '17 at 11:11
  • I'd like to add that with Java 8 lambdas & method reference the team is investigating to offer an intuitive stubbing API that follows the `when/then` approach. – bric3 Feb 24 '17 at 11:16
  • 9
    Just for the record: `doReturn()` has the **big** disadvantage of turning into YODA style coding of method calls. The thing later comes written down first that is. Most people read left to right; so you now have to constantly remember to reverse the return-when logic in your head. – GhostCat Feb 24 '17 at 13:40
  • `doReturn` is against human readable order (unless you read from right to left) – ACV Jan 11 '18 at 10:40
  • 2
    "if you've got the type wrong, you'll find out as soon as you run your test." Yes, provided the runtime type checking is implemented correctly. https://github.com/mockito/mockito/issues/1155 I know that this is dealing with checked-ness of exceptions, rather than return types, which is different; but this allows you to make your mocks do impossible things. With due respect to the mockito developers, I would hold more store in the type checking of the Java compiler than their library, and so would prefer to leverage the former where possible. – Andy Turner Jul 20 '18 at 08:00
  • I've had instances where `doReturn().when()` with the same arguments and methods _does not work_ when the `when().thenReturn()` approach does work. There is some subtle difference with the test framework when using Mock vs. Spy classes. If I'm able to determine why this is the case from the documentation, I'll come back. If someone knows, please enlighten us! – iterator Jun 18 '21 at 00:54
  • @iterator I would suggest you try to construct a test case that _predictably_ does what you think is the wrong thing, then post a fresh question here. I've never had any trouble with `doReturn/when` so I suspect you're doing something slightly wrong; but without seeing your code, it's impossible for me to help you. – Dawood ibn Kareem Jun 18 '21 at 02:35
319

Both approaches behave differently if you use a spied object (annotated with @Spy) instead of a mock (annotated with @Mock):

  • when(...) thenReturn(...) makes a real method call just before the specified value will be returned. So if the called method throws an Exception you have to deal with it / mock it etc. Of course you still get your result (what you define in thenReturn(...))

  • doReturn(...) when(...) does not call the method at all.

Example:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Test:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");
Tom
  • 16,842
  • 17
  • 45
  • 54
akcasoy
  • 6,497
  • 13
  • 56
  • 100
  • 63
    This behavior just works for spied objects, since are "wrapper" of real objects. In the case of mocked objects, it does not matter if it's when/thenReturn or doReturn/ when. Mocked objects never calls real methods. – Rafael Orágio Sep 11 '15 at 19:43
  • Could you please give more information why do we need use this functionality? I don't see practical use case. The intent of test is confirm correctness of the code under different use cases. If the calll of the method throws exception test should throw exception, not return a value – Gleichmut Jun 07 '17 at 03:19
  • @Gleichmut This was a hypothetical scenario, where i show the usage/advantage of doReturn. In a real application, a method which just returns an exception makes of course no sense.. but you have methods (probably not so thin like this one) which may throw exceptions in certain conditions.. – akcasoy Jun 30 '17 at 07:52
  • 2
    Just for clarification: The when().thenReturn()-method calls the actual method (of a spy - doesn't matter for mocks) only once. This happens in the line you specify the mock behaviour (when(**myClass.anotherMethodInClass()**.thenRet...). After that the actual method is never called again. Maybe good to know if you did expect some decorator logic when reading the explanation above. – Jonas Dec 17 '18 at 06:34
  • This doesn't seem like an advantage of `doReturn()`, it looks like an abuse of the library. The point of spying instead of pure mocking is to take advantage of real calls. They also warn against using Spies like this: https://github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes) (and recommend extending the class and overriding the method instead) – Matthew Read Jan 16 '19 at 17:56
  • I find your explanation so useful! Is there any related documentation for this issue? – Sang Yun Park May 20 '20 at 17:34
  • This should be the accepted answer instead, thank you – ericn Jun 09 '21 at 12:23
  • This answer is basically incomplete. It talks about spies, but it doesn't mention mocks. In my experience, most users of Mockito deal with mocks far more than they deal with spies. – Dawood ibn Kareem Jun 13 '21 at 19:46
  • @RafaelOrágio, Mocked objects might call real methods, e.g., `mock(Foo.class, CALLS_REAL_METHODS)`. – Ray Jasson Jan 20 '23 at 12:19
24

The Mockito javadoc seems to tell why use doReturn() instead of when() Use doReturn() in those rare occasions when you cannot use Mockito.when(Object).

Beware that Mockito.when(Object) is always recommended for stubbing because it is argument type-safe and more readable (especially when stubbing consecutive calls).

Here are those rare occasions when doReturn() comes handy:

1. When spying real objects and calling real methods on a spy brings side effects

List list = new LinkedList(); List spy = spy(list);

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)

when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing: doReturn("foo").when(spy).get(0);

2. Overriding a previous exception-stubbing:

when(mock.foo()).thenThrow(new RuntimeException());

//Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown. when(mock.foo()).thenReturn("bar");

//You have to use doReturn() for stubbing:

doReturn("bar").when(mock).foo(); Above scenarios shows a tradeoff of Mockito's elegant syntax. Note that the scenarios are very rare, though. Spying should be sporadic and overriding exception-stubbing is very rare. Not to mention that in general overridding stubbing is a potential code smell that points out too much stubbing.

11

Continuing this answer, There is another difference that if you want your method to return different values for example when it is first time called, second time called etc then you can pass values so for example...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

So it will return false when the method is called in same test case and then it will return false again and lastly true.

AZ_
  • 21,688
  • 25
  • 143
  • 191
  • This is also possible with `when(...).thenReturn(...)` - you can supply multiple arguments to the `thenReturn()` and it will do the same thing. – Bernie Jan 24 '23 at 22:09
7

The latter alternative is used for methods on mocks that return void.

Please have a look, for example, here: How to make mock to void methods with mockito

Community
  • 1
  • 1
vikingsteve
  • 38,481
  • 23
  • 112
  • 156