javajunitmockitopowermockito

mockito.verify() is giving wrong invocation count


I am trying the mockito.verify() feature. The method invocation takes place only once but, but verify is showing 3 invocations. The unit test has only one test, to ensure no other way this test gets affected.

Mockito.verify(utilClass, Mockito.times(1)).hello(); /// but invocation is 3 times, says the error

I have been looking at the log, which is also showing the invocation taking place only once. Added deliberate calling method utilClass.hello() more than once, then it's showing the correct number of invocations. But in the given code, where it is called once, it is appearing as called 3 times.

Class to be tested:

@Component
public class UtilClass {
    
    private static final Logger logger =  LoggerFactory.getLogger(UtilClass.class);

    public String hello() {
        logger.info("hello method invoked");
        return "Hello World,"+ hi();
    }
    
    private String hi() {
        logger.info("hi method invoked");
        return "Hi All";
    }
}
@Component
public class ClassWithDependency {

    @Autowired
    private UtilClass utilClass;

    public String welcome() {
        String msg = utilClass.hello();
        return msg;
    }

}

Test case


@InjectMocks
private ClassWithDependency classWithDependency;

@Mock
private UtilClass utilClass;

@Before
public void init() throws Exception {
        PowerMockito.when(utilClass,"hi").thenReturn("Hi Java");
        PowerMockito.when(utilClass.hello()).thenCallRealMethod();
    }


    @Test
    public void testMock() throws Exception {
        final String msg = classWithDependency.welcome();
        
        final String msgExpected = "Hello World,Hi Java";
        logger.info("welcome method called:{}",msg);
        
        PowerMockito.verifyPrivate(utilClass, Mockito.times(1)).invoke("hi");
        Mockito.verify(utilClass, Mockito.times(1)).hello();
        
        Assert.assertTrue(msg.equals(msgExpected));
    }

I am expecting the mockito.verify to be successful, but getting this error:

org.mockito.exceptions.verification.TooManyActualInvocations: 
utilClass.hello();
Wanted 1 time:
-> at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
But was 3 times:
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
    at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
.............

Solution

  • Finally make the test working, the solution is 'SPY'.. Spy on util class, so that not to tell which method to make real call. I am not sure how to inject spy, so used a setter..

    @InjectMocks private ClassWithDependency classWithDependency;

    private UtilClass mockUtil;
    
    @Before
    public void init() throws Exception {
        UtilClass utilClass = new UtilClass();
        mockUtil = PowerMockito.spy(utilClass);
        classWithDependency.setUtilClass(mockUtil); 
    }
    
    @Test
    public void testMock() throws Exception {
        PowerMockito.when(mockUtil,"hi").thenReturn("Hi Java"); 
        final String msg = classWithDependency.welcome();
        final String msgExpected = "Hello World,Hi Java";
        logger.info("welcome method called:{}",msg);
        PowerMockito.verifyPrivate(mockUtil, Mockito.times(1)).invoke("hi");
        Mockito.verify(mockUtil, Mockito.times(1)).hello();
        Assert.assertTrue(msg.equals(msgExpected));
    }