Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

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.

As always, the code is available over on GitHub.

 

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.