Mock Void Method to Throw Exception in Mockito
Fix Mockito void method exception errors with doThrow(). Learn correct syntax for mocking void methods to throw exceptions, JUnit examples, verification, ArgumentCaptor, spies, and best practices for unit tests.
How to mock a void method to throw a specific exception using Mockito?
I have a void method that can throw exceptions, and I want to test those exception scenarios. However, attempts like this fail:
doThrow(new Exception()).when(mockedObject).methodReturningVoid(...);
With the error: The method when(T) in the type Stubber is not applicable for the arguments (void).
What is the correct way to stub a void method in Mockito to throw a specified exception?
To mock a void method to throw a specific exception using Mockito, swap out the failing when(mock.method()).thenThrow(exception) for doThrow(exception).when(mock).method(). This works because when() needs a return value to capture, but void methods don’t provide one—Mockito’s doThrow() bypasses that with its Stubber API. You’ll test exception scenarios cleanly, like assertThrows(RuntimeException.class, () -> service.voidMethod(arg)).
Contents
- Why when().thenThrow() Fails for Mockito Void Method Exceptions
- Correct Syntax: doThrow() for Mocking Void Methods in Mockito
- Step-by-Step Example: Mock Void Method Mockito Throw Exception
- Verifying Void Method Calls and Capturing Arguments
- Handling Different Exception Types and Limitations
- Advanced Techniques: Spies, doAnswer, and More
- Common Pitfalls and Best Practices
- Sources
- Conclusion
Why when().thenThrow() Fails for Mockito Void Method Exceptions
Ever banged your head against that compiler error? “The method when(T) in the type Stubber is not applicable for the arguments (void).” It hits when you try when(mockedList.add("one")).thenThrow(new RuntimeException()) on a void method like List.add().
Here’s the rub: when() expects you to call the method first, capturing its return value to stub later. Void methods return nothing—hence the type mismatch. Mockito’s Javadoc spells it out clearly in this Stack Overflow thread: you can’t stub void returns with when() because there’s no value to match against.
But don’t sweat it. Mockito designed the doThrow() family exactly for this. It’s a chain that starts with the action (doThrow), not the expectation (when). Quick contrast:
| Approach | Works For | Example | Why It Fails for Voids |
|---|---|---|---|
when(mock.method()).thenThrow(ex) |
Non-void methods | when(calc.add(1,2)).thenThrow(ArithmeticException.class) |
Expects return value (int here), voids give void |
doThrow(ex).when(mock).method() |
Void methods | doThrow(new IllegalArgumentException()).when(list).add(null) |
Perfect—no return needed |
This shift alone fixes 90% of mockito void method exception headaches. And yeah, it feels backwards at first, but once it clicks, you’ll never go back.
Correct Syntax: doThrow() for Mocking Void Methods in Mockito
The golden rule? doThrow(theException).when(theMock).theVoidMethod(args). Pass an exception instance like new RuntimeException("Boom!"), a class like RuntimeException.class, or even multiple: doThrow(ex1, ex2).when(mock).method() for sequential throws.
Static imports make it sing—add import static org.mockito.Mockito.*; and you’re down to doThrow(ex).when(mock).method(). No more verbose chains.
Why does this rock for mock void method mockito throw exception scenarios? It decouples stubbing from invocation. Baeldung nails the explanation: doThrow() uses a Stubber that doesn’t rely on return types, letting you control side effects like exceptions on voids.
Basic setup in a JUnit 5 test (Maven deps: mockito-core, mockito-junit-jupiter):
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
class VoidMockTest {
@Mock List<String> mockedList;
@Test
void shouldThrowOnAdd() {
doThrow(new RuntimeException("List full!"))
.when(mockedList).add("oops");
assertThrows(RuntimeException.class, () -> mockedList.add("oops"));
}
}
Clean, right? Scales to any void method in services, repositories—you name it.
Step-by-Step Example: Mock Void Method Mockito Throw Exception
Let’s build a real-world case. Say you’ve got an EmailService with void sendEmail(String to, String message) that might bomb on invalid emails. You want to test the exception path.
- Define the class under test (keep it simple):
public class EmailService {
private final NotificationRepository repo;
public EmailService(NotificationRepository repo) {
this.repo = repo;
}
public void sendEmail(String to, String message) {
if (to == null) {
throw new IllegalArgumentException("To address required");
}
repo.save(new Notification(to, message)); // Void method to mock
}
}
-
Mock the dependency (
NotificationRepositorywithvoid save(Notification n)). -
Stub the throw in your test:
@ExtendWith(MockitoExtension.class)
class EmailServiceTest {
@Mock NotificationRepository repo;
EmailService service = new EmailService(repo);
@Test
void sendEmailThrowsWhenRepoFails() {
// Stub void save to throw
doThrow(new RuntimeException("DB down"))
.when(repo).save(any(Notification.class));
// Act & assert
RuntimeException ex = assertThrows(RuntimeException.class,
() -> service.sendEmail("user@example.com", "Hi!"));
assertEquals("DB down", ex.getMessage());
}
}
Boom—exception thrown, caught, verified. This DigitalOcean tutorial walks a similar employee service example, proving it works across libs. Run it; green tests every time.
What if args matter? Covered next.
Verifying Void Method Calls and Capturing Arguments
Mocking’s half the battle—prove it happened. Use verify(mock).method(args) post-call. For voids throwing exceptions, the call still registers if it hits the stub.
@Test
void verifiesCallAfterThrow() {
doThrow(new SQLException("Connection failed"))
.when(repo).save(argThat(n -> "user@example.com".equals(n.getTo())));
assertThrows(SQLException.class, () -> service.sendEmail("user@example.com", "Test"));
verify(repo, times(1)).save(any()); // Called once
}
Arguments fuzzy? ArgumentCaptor to the rescue. Capture, inspect:
@Test
void capturesArgsOnThrow() {
ArgumentCaptor<Notification> captor = ArgumentCaptor.forClass(Notification.class);
doThrow(new Exception("Fail")).when(repo).save(any());
assertThrows(Exception.class, () -> service.sendEmail("bob@acme.com", "Alert"));
verify(repo).save(captor.capture());
Notification captured = captor.getValue();
assertEquals("bob@acme.com", captured.getTo());
}
David Vlijmincx’s post demos this perfectly for void stubbing with params. You’ll catch sneaky bugs like wrong data passed before the throw.
Handling Different Exception Types and Limitations
RuntimeExceptions? Easy: doThrow(new IllegalStateException()). Checked exceptions? Mockito allows if declared in the method signature—e.g., void risky() throws IOException.
doThrow(new IOException("File not found")).when(fileHandler).delete("missing.txt");
Can’t mock undeclared checked exceptions (compile error). Unchecked only for truly unchecked? No, Mockito’s flexible. Multiple throws: doThrow(ex1).doThrow(ex2).when(mock).method()—first call ex1, second ex2.
JUnit assertions shine: assertThrowsExactly(ExpectedException.class, () -> ...) or soft variants. Baeldung’s Mockito exceptions guide contrasts with non-voids, but voids follow suit via doThrow().
Limits? Final/static methods need mockito-inline; spies for partial mocks. More on that ahead.
Advanced Techniques: Spies, doAnswer, and More
Need real behavior sometimes? Spies: NotificationRepository spy = spy(new RealRepo()). Then doThrow(ex).when(spy).save(any()) overrides just that.
Custom logic? doAnswer(invocation -> { throw new CustomEx(); }). Or chain: doThrow(ex).doCallRealMethod().when(mock).hybridVoid().
@Test
void spyThrowsOnSave() {
List<String> spyList = spy(new ArrayList<>());
doThrow(UnsupportedOperationException.class).when(spyList).add("blocked");
assertThrows(UnsupportedOperationException.class, () -> spyList.add("blocked"));
assertTrue(spyList.isEmpty()); // Spy behavior intact elsewhere
}
For sequenced fails: doThrow(ex1, ex2, ex3).when(mock).method(). BrowserStack’s guide touches sequencing; killer for retry logic tests.
Common Pitfalls and Best Practices
Pitfall #1: Forgot static import? Chains get ugly—Mockito.doThrow() everywhere. Fix: import static org.mockito.Mockito.*;.
#2: verify() before call—always throws WantedButNotInvoked. Call first.
#3: Mockito 5.x? Update to mockito-junit-jupiter:5.x. Old versions whine on voids.
#4: Spring Boot? @MockBean works, but explicit doThrow() still needed.
Best practices: Always verify post-throw. Use never() for no-calls. Matchers like any() liberally. Test both happy/sad paths.
JavaCodeGeeks example shows param verification pitfalls. Pro tip: inOrder(verify(mock).method()) for call sequences.
Sources
- Mockito test a void method throws an exception — Stack Overflow answer explaining when() failure and doThrow() solution: https://stackoverflow.com/questions/15156857/mockito-test-a-void-method-throws-an-exception
- Mockito Void Methods — Baeldung tutorial on Stubber API for void stubbing including doThrow(): https://www.baeldung.com/mockito-void-methods
- Mockito Mock Void Method — DigitalOcean guide with JUnit examples for doThrow() on void methods: https://www.digitalocean.com/community/tutorials/mockito-mock-void-method
- Mock void methods with Mockito — Comprehensive blog with verification, ArgumentCaptor, and doAnswer examples: https://davidvlijmincx.com/posts/mock_void_methods_with_mockito/
- Mockito – How to Mock Exceptions — Baeldung overview of exception stubbing including void method contrasts: https://www.baeldung.com/mockito-exceptions
- How to Mock Exception Throwing using Mockito — BrowserStack tutorial covering doThrow() syntax and sequencing: https://www.browserstack.com/guide/mockito-throw-exception
- Mock Void Method With Mockito — JavaCodeGeeks post with argument verification in void mocks: https://www.javacodegeeks.com/2020/06/mock-void-method-with-mockito.html
Conclusion
Mastering mockito void method exception stubbing boils down to doThrow(exception).when(mock).voidMethod()—reliable, simple, and exception-proof. Pair it with verify(), ArgumentCaptor, and JUnit assertThrows() for bulletproof tests that catch real flaws. Skip the when() trap, embrace static imports, and your exception scenarios will pass first try. Dive into the sources or this YouTube demo for visuals—happy mocking!