STSISA
STSISA

Reputation: 61

PowerMockito verifyTimes Always passets private method

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?

Upvotes: 2

Views: 403

Answers (2)

xerx593
xerx593

Reputation: 13281

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! :-)

Upvotes: 1

STSISA
STSISA

Reputation: 61

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"); 
    }
}

Upvotes: 1

Related Questions