why Mock object has doreturn and thenreturn for mock?

Avinash Jethy picture Avinash Jethy · Dec 29, 2016 · Viewed 7.7k times · Source

Note: I understand that in spy we can differenciate among these two. I went all over internet but I still some doubts on doreturn/when and when/thenreturn in Mockito .Below is my doubt,

1)Are doreturn/when and when/thenreturn acts same for mock object ? i.e: its does not matter whether you call doreturn/when or when/thenreturn for a mock object it will not call real method , but a stubbed call. is my understanding is correct on this ?

2)doreturn/when and when/thenreturn makes a difference only for spy objects in Mockito. i.e doreturn/when - will not call real methos and when/thenreturn will call real method.Is my understanding correct on this ?

If my understanding on above 2 points are correct then we should always use doreturn/when so that we dont need to learn 2 syntax ,Right ?

Answer

sisyphus picture sisyphus · Dec 29, 2016

The Mockito documentation for doReturn() states:

You can use doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() in place of the corresponding call with when(), for any method. It is necessary when you

  • stub void methods
  • stub methods on spy objects (see below)
  • stub the same method more than once, to change the behaviour of a mock in the middle of a test.

and also...

Use doReturn() in those rare occasions when you cannot use when(Object).

With an example given of...

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();

In general, you should use the when(...).thenReturn(...) syntax and the occasions when the doReturn(...).when(...) syntax is useful are rare. However, it's important to note that the when(...) pattern is required for mocking void methods, which are not rare. It's just the doReturn(...) syntax which is less commonly used.

To specifically answer your questions:

  1. No, the two syntaxes work slightly differently - the 'doReturn(...)' is able to set up the mock object to record a behaviour before the mocked method is called, whereas the 'when(...)' syntax works by doing some behind-the-scenes jiggery-pokery to set up a stub handler which the 'thenReturn(...)' method can work on. They'll usually have the same effect but the implementation differences become apparent in the corner case above.

  2. For a mock, when(...) calls the stubbed method on the mock object. That's why the corner case above around re-defining the stubs behaviour is important.