1. Overview
In this tutorial, weβll talk about a common error we can face when we use Mockito. The Exception message is:
Wanted but not invoked:
// class name and location
Actually, there were zero interactions with this mock.
Letβs understand the potential sources of this error and how to fix it.
2. Example Setup
First, letβs create the class weβll mock later on. It contains a lone method, which always returns the String, βBaeldungβ:
class Helper {
String getBaeldungString() {
return "Baeldung";
}
}
Letβs now create our main class. It declares a Helper instance at the class level. Weβll want to mock this instance during our unit test:
class Main {
Helper helper = new Helper();
String methodUnderTest(int i) {
if (i > 5) {
return helper.getBaeldungString();
}
return "Hello";
}
}
On top of that, we defined a method that accepts an Integer as a parameter and returns:
- the result of the call to getBaeldunString() if the Integer is greater than 5
- a constant if the Integer is less than or equal to 5
3. Real Method Called Instead of Mock
Letβs try to write a unit test for our method. Weβll use the @Mock annotation to create a mocked Helper. Weβll also invoke MockitoAnnotations.openMocks() to enable Mockito annotations. In the test method, weβll call methodUnderTest() with the parameter 7 and check that it delegates to getBaeldungString():
class MainUnitTest {
@Mock
Helper helper;
Main main = new Main();
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void givenValueUpperThan5_WhenMethodUnderTest_ThenDelegatesToHelperClass() {
main.methodUnderTest(7);
Mockito.verify(helper)
.getBaeldungString();
}
}
Letβs now run our test:
Wanted but not invoked:
helper.getBaeldungString();
-> at com.baeldung.wantedbutnotinvocked.Helper.getBaeldungString(Helper.java:6)
Actually, there were zero interactions with this mock.
The problem is that we called the constructor to instantiate a Main object. Thus, the Helper instance was created by the call to new(). Consequently, we use a real Helper object instead of our mock. To fix the issue, we need to add @InjectMocks on top of our Main object creation:
@InjectMocks
Main main = new Main();
As a side note, weβll fall back again into the same problem if we replace the mocked instance with a real object at any point of methodUnderTest():
String methodUnderTest(int i) {
helper = new Helper();
if (i > 5) {
return helper.getBaeldungString();
}
return "Hello";
}
In a nutshell, we have two points of attention here:
- The mocks should be correctly created and injected.
- The mocks shouldnβt be replaced with other objects at any point.
4. Method Not Invoked
Weβll now write a new unit test. It will check that passing 3 as an argument to methodUnderTest() results in a call to getBaeldungString():
@Test
void givenValueLowerThan5_WhenMethodUnderTest_ThenDelegatesToGetBaeldungString() {
main.methodUnderTest(3);
Mockito.verify(helper)
.getBaeldungString();
}
Once again, we can run the test:
Wanted but not invoked:
helper.getBaeldungString();
-> at com.baeldung.wantedbutnotinvocked.Helper.getBaeldungString(Helper.java:6)
Actually, there were zero interactions with this mock.
This time, letβs carefully read the error message. It says that we didnβt interact with the mock. Letβs now check back our methodβs specification: 3 is less than 5, so methodUnderTest() returns a constant instead of delegating to getBaeldungString(). Thus, our test is contradictory to the specification.
In such a case, we have only two possible conclusions:
- The specification is correct: We need to fix our test because the verification is useless.
- The test is correct: Thereβs a bug in our code that we need to address.
5. Conclusion
In this article, we called Mockito.verify() without interacting with the mock and got an error. We pointed out that we need to inject and use the mocks properly. We also saw this error arise with an incoherent test.
