Question
How can I mock methods that have a void return type using Mockito?
I implemented something like an observer pattern, but I am not sure how to test it correctly with Mockito.
I looked for examples online, but I could not find one that clearly matched my case.
My code is roughly like this:
public class World {
List<Listener> listeners;
void addListener(Listener item) {
listeners.add(item);
}
void doAction(Action goal, Object obj) {
setState("i received");
goal.doAction(obj);
setState("i finished");
}
private String state;
// getter and setter for state
}
public class WorldTest implements Listener {
@Test
public void word() {
World w = mock(World.class);
w.addListener(this);
// ...
}
}
interface Listener {
void doAction();
}
The expected behavior is not happening when World is mocked.
I want to observe the system state changes and make assertions based on them. How should I test or mock this properly with Mockito?
Short Answer
By the end of this page, you will understand how Mockito handles void methods, when to use doNothing(), doThrow(), and doAnswer(), and why fully mocking the class under test often prevents real behavior from running. You will also learn how to test state changes and interactions correctly in an observer-style design.
Concept
Mockito can mock void methods, but they work a little differently from methods that return a value.
For a normal method, you often write:
when(service.getName()).thenReturn("Alice");
That style does not work for void methods, because there is no return value to configure.
Instead, Mockito provides the do...when(...) syntax:
doNothing().when(mock).someVoidMethod();
doThrow(new RuntimeException()).when(mock).someVoidMethod();
doAnswer(invocation -> {
// custom behavior
return null;
}).when(mock).someVoidMethod();
Why this matters
In real code, void methods are common for:
- notifications
- logging
- sending events
- mutating object state
- updating other objects
Testing them usually means one of these:
- verifying that the method was called
- simulating side effects
- checking how other code reacts when the method throws an exception
The key issue in your example
Mental Model
Think of a mock as a cardboard stand-in for a real object.
It looks like the object from the outside, but it does not do any real work unless you tell it exactly what to do.
So if you create:
World w = mock(World.class);
that mock is like an empty actor reading no lines. Calling:
w.doAction(...);
does not execute your real doAction() logic.
A better mental model is:
- Real object under test = the machine you want to inspect
- Mocks = fake buttons, sensors, or connected devices around it
If you want to see whether the machine changes state correctly, use the real machine. If you want to control or observe the things connected to it, mock those.
Syntax and Examples
With Mockito, void methods are configured using do...when(...).
Core syntax
doNothing().when(mock).voidMethod();
doThrow(new IllegalStateException()).when(mock).voidMethod();
doAnswer(invocation -> {
// custom side effect
return null;
}).when(mock).voidMethod();
Example 1: Verify that a void method was called
import static org.mockito.Mockito.*;
Listener listener = mock(Listener.class);
listener.doAction();
verify(listener).doAction();
This is the most common case. You do not always need to stub a void method at all. Often, you simply call the code and verify the interaction.
Example 2: Make a void method throw an exception
import static org.mockito.Mockito.*;
Listener listener = mock(Listener.class);
doThrow(new RuntimeException("failed")).(listener).doAction();
listener.doAction();
Step by Step Execution
Consider this code:
public interface Action {
void doAction(Object obj);
}
public class World {
private String state;
public void doAction(Action goal, Object obj) {
setState("i received");
goal.doAction(obj);
setState("i finished");
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
And this test:
World world = new World();
Action action = mock(Action.class);
world.doAction(action, "file.txt");
What happens step by step
worldis a .
Real World Use Cases
void method mocking appears in many practical situations.
Event and observer systems
A listener often reacts through a void method:
listener.onMessage(message);
Tests usually verify that the listener was notified.
Logging and auditing
Services may call:
auditService.record(userAction);
The method returns nothing, but tests may verify it was called with the right data.
Email or notification sending
emailSender.sendWelcomeEmail(user);
You usually do not want to send a real email in a test, so you mock the sender and verify the call.
External side effects
Examples include:
- writing files
- publishing events
- sending metrics
- updating caches
These methods often return void, so mocks prevent real side effects while still letting tests check behavior.
Exception-path testing
A void dependency may fail:
doThrow( ()).(emailSender).sendWelcomeEmail(user);
Real Codebase Usage
In real projects, developers rarely mock everything. They usually test one unit of behavior at a time.
Common pattern: real class, mocked dependencies
OrderService service = new OrderService(paymentGateway, emailSender);
In a test:
OrderServiceis realpaymentGatewaymay be mockedemailSendermay be mocked
This lets the service logic run while dependencies stay controlled.
Verifying void interactions
Common in service tests:
verify(emailSender).sendWelcomeEmail(user);
verify(auditService).record("USER_CREATED");
Using doThrow() for error handling
Teams often test failure branches like this:
doThrow(new IOException()).when(fileWriter).write(data);
Then they check whether the application:
- logs the error
- retries
- returns a safe response
Common Mistakes
1. Mocking the class you want to test
Broken approach:
World world = mock(World.class);
world.doAction(action, "data");
Why it fails:
- the real
doAction()method does not run - state is not updated
Better:
World world = new World();
Action action = mock(Action.class);
2. Using when(...).thenReturn(...) on a void method
Broken code:
when(listener.doAction()).thenReturn(...);
Why it fails:
voidmethods do not return a value
Correct approach:
doNothing().when(listener).doAction();
or simply verify the call without stubbing.
Comparisons
| Approach | What it does | Good for | Common risk |
|---|---|---|---|
mock(Class) | Creates a fake object with no real behavior by default | Isolating dependencies | Real logic does not run |
spy(new Class()) | Wraps a real object and calls real methods by default | Partial mocking | Can make tests complex |
| Real object | Executes real code normally | Testing state changes and business logic | Harder if dependencies are external |
| Mockito syntax | Used for | Example |
|---|---|---|
when(...).thenReturn(...) | Non-void methods |
Cheat Sheet
Quick rules
- Use
do...when(...)forvoidmethods - Use
when(...).thenReturn(...)for non-void methods - Do not mock the class you want to test unless you have a specific reason
- Mock collaborators, not the main behavior under test
Void method syntax
doNothing().when(mock).voidMethod();
doThrow(new RuntimeException()).when(mock).voidMethod();
doAnswer(invocation -> {
return null;
}).when(mock).voidMethod();
Verify calls
verify(mock).voidMethod();
verify(mock, never()).voidMethod();
verify(mock, times(2)).voidMethod();
Best practice for your scenario
World world = new World();
Action action = mock(Action.class);
world.doAction(action, "data");
verify(action).doAction("data");
assertEquals("i finished", world.getState());
FAQ
How do you mock a void method in Mockito?
Use doNothing(), doThrow(), or doAnswer() with when(...), for example:
doThrow(new RuntimeException()).when(service).run();
Can I use when(...).thenReturn(...) with a void method?
No. That syntax only works for methods that return a value.
Why is my mocked object not changing state?
Because a Mockito mock does not run real code by default. If you want real state changes, use a real object or a spy.
Should I mock the class I am testing?
Usually no. Create a real instance of the class under test and mock its dependencies.
Do I need doNothing() for every void method?
No. Mockito does nothing by default for mocked void methods. Often you can skip stubbing and just use verify(...).
How do I test that a void method was called with the right argument?
Use verify(...) or ArgumentCaptor.
When should I use ?
Mini Project
Description
Build a small Java test scenario where a World object updates its internal state before and after calling a dependency with a void method. This demonstrates the correct testing strategy: keep the main object real, mock the collaborator, and verify both state changes and interactions.
Goal
Create a test that confirms a void dependency is called and that the main object's state changes as expected.
Requirements
- Create a
Worldclass with astatefield and adoActionmethod. - Create an
Actioninterface with avoid doAction(Object obj)method. - Write a JUnit test that uses a real
Worldand a mockedAction. - Verify that the mocked
Actionis called with the expected argument. - Assert that the final
statevalue is correct after execution.
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.