Exception : mockito wanted but not invoked, Actually there were zero interactions with this mock
Categories:
Resolving 'Mockito wanted but not invoked' Errors

Understand and fix the common Mockito error: 'Wanted but not invoked, Actually there were zero interactions with this mock' in your Java unit tests.
When writing unit tests with Mockito, encountering the Wanted but not invoked
error, often accompanied by Actually there were zero interactions with this mock
, is a common hurdle. This error indicates that while you've set up an expectation for a method call on a mock object, that method was never actually called during the execution of the code under test. This article will delve into the root causes of this error and provide practical solutions to help you resolve it, ensuring your tests accurately reflect your code's behavior.
Understanding the 'Wanted but not invoked' Error
Mockito's verify()
method is used to check if certain interactions happened on a mock object. When you write verify(mockObject).someMethod();
, you're telling Mockito to confirm that someMethod()
was called on mockObject
at least once. If this call doesn't occur, Mockito throws the Wanted but not invoked
error. The additional message, Actually there were zero interactions with this mock
, further clarifies that no methods were called on the mock at all, suggesting a fundamental disconnect between your test setup and the actual code execution.
flowchart TD A[Test Setup] --> B{Mock Object Created?} B -- Yes --> C{Method Call Expected (verify)?} C -- Yes --> D[Code Under Test Executes] D --> E{Mock Method Actually Called?} E -- No --> F["Error: Wanted but not invoked"] E -- Yes --> G[Test Passes Verification] B -- No --> H[Error: Mock Not Used] C -- No --> I[No Verification, Test Might Pass Incorrectly]
Flowchart illustrating the lifecycle of a Mockito verification and potential error points.
Common Causes and Solutions
This error typically stems from one of a few common issues. Identifying the exact cause in your specific scenario is key to resolving it.
1. Cause 1: Mock Not Injected or Used
The most frequent reason is that the mock object you're verifying is not actually being used by the class under test. This can happen if the mock isn't properly injected into the SUT (System Under Test), or if the SUT uses a real dependency instead of the mock.
2. Solution 1: Verify Injection
Ensure your mock is correctly injected. If using @InjectMocks
and @Mock
, make sure the fields are correctly annotated and that the MockitoAnnotations.openMocks(this)
or MockitoJUnitRunner
is used. If manually injecting, double-check that the mock instance is passed to the SUT's constructor or setter method.
3. Cause 2: Incorrect Method Signature or Arguments
You might be verifying a method call with a different signature or different arguments than what is actually being called. Mockito is strict about matching method calls.
4. Solution 2: Use ArgumentMatchers
If the arguments can vary, use Mockito's ArgumentMatchers
(e.g., anyString()
, anyInt()
, eq("specificValue")
). If you're verifying a method with specific arguments, ensure they exactly match what the code under test passes. Debugging the SUT to see the actual arguments passed can be very helpful here.
5. Cause 3: Method Not Reached
The code path that calls the mocked method might not be executed due to conditional logic, exceptions, or early returns in your SUT.
6. Solution 3: Debug and Trace Execution
Step through your test and the SUT's method using a debugger. Observe the execution flow and confirm that the line of code responsible for calling the mocked method is indeed reached. Adjust your test input or SUT state to ensure the correct path is taken.
7. Cause 4: Verifying the Wrong Object
You might have multiple instances of a dependency, and you're verifying the wrong one. For example, if your SUT creates a new instance of a dependency internally, your injected mock won't be used.
8. Solution 4: Isolate Dependencies
Ensure that all dependencies of your SUT are either real objects that you don't care to mock, or are properly mocked and injected. Avoid creating new instances of dependencies directly within the SUT if you intend to mock them for testing.
Example: Demonstrating the Error and Its Fix
Let's look at a simple example where this error might occur and how to fix it.
public class MyService {
private MyRepository repository;
public MyService(MyRepository repository) {
this.repository = repository;
}
public String processData(String input) {
if (input == null || input.isEmpty()) {
return "Invalid input";
}
// Simulate some processing
String processed = input.toUpperCase();
// This line is the one we want to mock/verify
return repository.save(processed);
}
}
public interface MyRepository {
String save(String data);
}
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
public class MyServiceTest {
@Mock
private MyRepository mockRepository;
@InjectMocks
private MyService myService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testProcessData_errorScenario() {
// This test will fail with 'Wanted but not invoked'
// because the condition in MyService prevents save() from being called.
String result = myService.processData(null);
assertEquals("Invalid input", result);
// This verification will fail!
verify(mockRepository).save(anyString());
}
@Test
void testProcessData_successScenario() {
when(mockRepository.save("HELLO")).thenReturn("SAVED: HELLO");
String result = myService.processData("hello");
assertEquals("SAVED: HELLO", result);
// This verification will pass
verify(mockRepository).save("HELLO");
}
}
In testProcessData_errorScenario()
, myService.processData(null)
returns "Invalid input" and exits before repository.save()
is ever called. Therefore, verify(mockRepository).save(anyString())
fails with the Wanted but not invoked
error. The testProcessData_successScenario()
demonstrates the correct usage where the mock's method is indeed called and verified.