doReturn vs when thenReturn Mockito | Java Fresher
Fast recall
Quick revision
Core answer
when(spy.read()).thenReturn(value) evaluates spy.read() during setup, so a spy's real method runs first. doReturn(value).when(spy).read() installs the stub without that call. Prefer the usual when(...).thenReturn(...) for ordinary mocks and for safe spy calls; use doReturn when invoking the real spy method during setup would fail or cause side effects. Void methods use doNothing, doThrow, or doAnswer, not doReturn.Interview-ready guide
Interview answer
Both syntaxes stub a non-void method, but they differ during setup. In when(spy.read()).thenReturn(value), Java evaluates spy.read() before Mockito completes the stubbing. A normal mock returns a default value, but a spy calls the real method, which may access a database, mutate state, or throw.
doReturn(value).when(spy).read() installs the stub without executing read during setup. For example, stubbing spyList.get(0) on an empty real list needs doReturn("first").when(spyList).get(0) to avoid IndexOutOfBoundsException.
I use the ordinary when style for regular mocks and for spy methods that are safe to call. I use doReturn only for the unsafe eager-call case, because it provides less compile-time type checking. Void methods are different: they use doNothing, doThrow, or doAnswer.
doReturn vs when thenReturn Mockito | Java Fresher
Direct Answer
Both forms can stub a non-void method. when(spy.read()).thenReturn(value) evaluates spy.read() during setup, so a spy's real method runs first. doReturn(value).when(spy).read() installs the stub without that call. Prefer the usual when(...).thenReturn(...) for ordinary mocks and for safe spy calls; use doReturn when invoking the real spy method during setup would fail or cause side effects. Void methods use doNothing, doThrow, or doAnswer, not doReturn.
Code Example
@ExtendWith(MockitoExtension.class)
class PaymentServiceTest {
@Spy
private PaymentService spyService = new PaymentService();
@Test
void dangerousStubbing() {
// WRONG: when() calls the real checkFraud method during setup
// If checkFraud throws exception or has side effects, test fails here
when(spyService.checkFraud("card123")).thenReturn(false);
var result = spyService.processPayment("card123", 100.0);
assertTrue(result); // stub applied, but real method ran once during setup
}
@Test
void safeStubbing() {
// CORRECT: doReturn never invokes the real checkFraud method
doReturn(false).when(spyService).checkFraud("card123");
var result = spyService.processPayment("card123", 100.0);
assertTrue(result); // stub applied cleanly, no unwanted execution
}
@Test
void withMockBothWork() {
var mockRepo = mock(OrderRepository.class);
// Both syntaxes identical for mocks—no real method exists
when(mockRepo.findById(1L)).thenReturn(Optional.of(new Order(1L, "Book")));
doReturn(Optional.of(new Order(2L, "Pen"))).when(mockRepo).findById(2L);
assertEquals("Book", mockRepo.findById(1L).get().item());
assertEquals("Pen", mockRepo.findById(2L).get().item());
}
}
class PaymentService {
boolean processPayment(String cardNumber, double amount) {
return !checkFraud(cardNumber); // calls method we want to stub
}
boolean checkFraud(String cardNumber) {
throw new RuntimeException("Real fraud check—slow and flaky!");
}
}
Common Mistakes & Pitfalls
- Using when().thenReturn() with spies: This is the number one mistake. Freshers copy-paste stubbing code from mock examples and apply it to spies. The real method runs during test setup, throws an exception or triggers a database call, and the test fails mysteriously before the actual test logic executes. Always grep for @Spy in your test class and verify you're using doReturn syntax.
- Not understanding when() evaluates the call: Freshers think when(spy.method()) is just syntax, not an actual method invocation. It's not magic—Java executes that method call to determine what you're stubbing. For spies, that means real code runs.
- Inconsistent syntax mixing: Using when().thenReturn() for some stubs and doReturn().when() for others in the same test without reason creates confusion. Pick doReturn consistently for spies, when consistently for mocks.
Check your understanding
Answer these without looking back at the article.
- How do you stub a void method in Mockito?
- What is doAnswer() used for?
- How do you make a mock throw an exception?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.