Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static mocking with PowerMock and Mockito not working

I'm trying to verify that the Collections.shuffle() method was called in one of my classes. I read through the (little) documentation on PowerMock with Mockito and read through the other SO questions that dealt with this issue and didn't get a resolution.

@RunWith(PowerMockRunner.class)
@PrepareForTest(Collections.class)
public class MyTest {

    @Test
    public void testShuffle() {
        PowerMockito.mockStatic(Collections.class);
        PowerMockito.doCallRealMethod().when(Collections.class);
        Collections.shuffle(Mockito.anyListOf(Something.class));

        ClassToTest test = new ClassToTest();
        test.doSomething();

        PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
        Collections.shuffle(Mockito.anyListOf(Something.class));
    }
}

public class ClassToTest {
    private final List<Something> list;
    // ...
    public void doSomething() {
        Collections.shuffle(list);
        // do more stuff
    }
}

Given the above code, I expect the unit test pass. However, the unit test fails as follows:

Wanted but not invoked java.util.Collections.shuffle([]);
Actually, there were zero interactions with this mock.

What am I doing wrong?

Thanks

EDIT: As per the suggestion below I tried the following, and I get the same error.

@RunWith(PowerMockRunner.class)
@PrepareForTest(Collections.class)
public class MyTest {

    @Test
    public void testShuffle() {
        PowerMockito.mockStatic(Collections.class);

        ClassToTest test = new ClassToTest();
        test.doSomething();

        PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
        Collections.shuffle(Mockito.anyListOf(Something.class));
    }
}
like image 604
Pradeep Gollakota Avatar asked Jul 30 '13 05:07

Pradeep Gollakota


2 Answers

This is a rather old question, but I'd still like to clarify that the accepted answer is in fact incorrect. By executing the following code,

PowerMockito.mockStatic(Collections.class);
Collections.shuffle(Mockito.anyListOf(Something.class));

all verifies will always pass afterwards:

PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));

even if you do not call test.doSomething(); the provided test in the answer will still pass. The correct way to test this is to actually check if the items in the List have been sorted correctly.

like image 127
tmetten Avatar answered Sep 25 '22 06:09

tmetten


You can either mock/verify the java.util.Collections.shuffle([]) method or call the real implementation (with PowerMockito.doCallRealMethod()). But you can't do both.

If you remove

PowerMockito.doCallRealMethod().when(Collections.class);

the call will be verified and the test will pass.

https://powermock.googlecode.com/svn/docs/powermock-1.4.7/apidocs/org/powermock/api/mockito/PowerMockito.html#doCallRealMethod%28%29

This code works for me:

package test;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Collections.class)
public class MyTest {

    @Test
    public void testShuffle() {
        PowerMockito.mockStatic(Collections.class);
/*        PowerMockito.doCallRealMethod().when(Collections.class);  remove this line */
        Collections.shuffle(Mockito.anyListOf(Something.class));

        ClassToTest test = new ClassToTest();
        test.doSomething();

        PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
        Collections.shuffle(Mockito.anyListOf(Something.class));
    }
}

class ClassToTest {
    private List<Something> list = new LinkedList<Something>();
    // ...
    public void doSomething() {
        Collections.shuffle(list);
        // do more stuff
    }
}
class Something {
}
like image 31
Christopher Roscoe Avatar answered Sep 26 '22 06:09

Christopher Roscoe