2
public class TestedClass
{
    
    public void publicMethod() 
    {
        privateMethod();
    }
    
    private void privateMethod() 
    {
    }
}

I would like to test with PowerMockito that the private method is called exactly once.

Here's my test class:

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
public class TestedClassTest
{
    
    @Before
    public void setUp()
    {
    }
    
    @Test
    public void testPrivateMethodCalledOnce() throws Exception 
    {
        TestedClass spy = PowerMockito.spy(new TestedClass());
        spy.publicMethod();
        
        PowerMockito.verifyPrivate(spy, Mockito.times(772)).invoke("privateMethod"); 
    }
}

Despite only being called once this test passes. Even if I comment privateMethod inside the public method the test seems too pass.

public class TestedClass
{

    public void publicMethod() 
    {
        //privateMethod(); <-- test still passes
    }

    private void privateMethod() 
    {
    }
}

Does anyone have an idea what I did wrong? And does anyone know how to verify that the private method was called exactly once in the unit test?

STSISA
  • 61
  • 4
  • Does this answer your question? [Powermock verify private static method call in non static method](https://stackoverflow.com/questions/16515809/powermock-verify-private-static-method-call-in-non-static-method) – Progman Dec 22 '21 at 19:41

2 Answers2

1

The problem could be is, that:

.invoke("privateMethod")

can be interpreted as:

  1. void invoke(String methodToVerify, Object... arguments) javadoc, which we (obviously) want. Or
  2. void invoke(Object... arguments) javadoc, which is different and discovers the (private) method not by name, but by "arguments".

So a solution could be (to avoid incorrect overload):

.invoke("privateMethod", new Object[0]) // which still *could* be 
   // confused with Object... but I "hope" the String in front saves us!:)
// if this works: .invoke("privateMethod", null) should also work.

Or to use one of the alternatives corerctly.#


But this is often the problem with "overloaded libs" ... varargs makes things even worse/potentially in-deterministic! :-)

xerx593
  • 12,237
  • 5
  • 33
  • 64
  • @all: Watch out for (Power)Mockito method (matchers/verifiers) overloads!! – xerx593 Dec 22 '21 at 19:54
  • 1
    thanks for replying. Really learned from your example. In this case it seems as the "@PrepareForTest" annotation was missing in the test. – STSISA Dec 23 '21 at 12:01
  • Actually I was completely wrong! :-):-):-) Thank You anyway! – xerx593 Dec 23 '21 at 12:49
  • well I learned something new and also you didn't give me a lecture on why it's wrong to test a private class =). Thanks anyway – STSISA Dec 23 '21 at 13:10
1

It seems as if I need to include the @PrepareForTest annotation in this particular test to make it work. Now the test fails which it was supposed to do. Also - it works when I change to Mockito.times(1).

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PrepareForTest(TestedClass.class) // <--- I didn't include this in the question
public class TestedClassTest
{
    
    @Before
    public void setUp()
    {
    }
    
    @Test
    public void testPrivateMethodCalledOnce() throws Exception 
    {
        TestedClass spy = PowerMockito.spy(new TestedClass());
        spy.publicMethod();
        
        PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke("privateMethod"); 
    }
}
STSISA
  • 61
  • 4