I am writing unit tests for a service layer where I need to mock a repository method that returns void. Typically, I use when(mock.method()).thenReturn(value), but since the method doesn't return anything, the compiler throws an error. How do I handle scenarios where I need a void method to throw an Exception, do nothing (to override a default behavior), or capture arguments for validation? Is there a specific "family" of methods like doThrow() or doAnswer() that I should be using instead of the standard when()?
3 answers
When dealing with void methods, you must use the "do" family of methods because the standard when(mock.method()) requires the method to return a value to pass as an argument. The syntax is slightly reversed:
-
To throw an exception:
doThrow(new Exception()).when(mockInstance).voidMethod(); -
To do nothing (explicitly):
doNothing().when(mockInstance).voidMethod(); -
To execute custom logic:
doAnswer(invocation -> { ... }).when(mockInstance).voidMethod();
Note that you call the behavior first (doThrow), then .when(mockInstance), and finally the method call itself. This approach works because the method call inside .when(...) isn't actually being evaluated as a return value, allowing the Mockito framework to intercept it correctly.
That makes sense for stubbing behavior, but what if I don't need the method to do anything, but I want to verify that it was called with specific parameters? Can I still use the standard verify(mock).voidMethod(argument) syntax, or do void methods require a different verification strategy as well?
If you are using BDD (Behavior Driven Development) style with BDDMockito, the syntax changes to willThrow(new Exception()).given(mockInstance).voidMethod();. It's essentially the same logic but fits better with the given/when/then structure of BDD tests.
I agree with Alex. Switching to willThrow or willAnswer makes the tests read much more like natural language. I've found it helps non-technical stakeholders understand the test intent much faster during code reviews.
Sarah, verification remains exactly the same! You can use verify(mock, times(1)).voidMethod(any()); just like you would for methods with return types. The "do" family is strictly for stubbing (telling the mock how to act), whereas verify is for behavioral testing (checking what happened after the test ran).