5

我正在尝试验证 Collections.shuffle() 方法是否在我的一个类中被调用。我用 Mockito 通读了关于 PowerMock 的(小)文档,并通读了处理这个问题但没有得到解决的其他 SO 问题。

@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
    }
}

鉴于上面的代码,我希望单元测试通过。但是,单元测试失败如下:

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

我究竟做错了什么?

谢谢

编辑: 根据下面的建议,我尝试了以下方法,但我得到了同样的错误。

@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));
    }
}
4

2 回答 2

5

这是一个相当古老的问题,但我仍然想澄清接受的答案实际上是不正确的。通过执行以下代码,

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

所有验证都将在之后通过:

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

即使您不调用test.doSomething();答案中提供的测试,仍然会通过。测试这一点的正确方法是实际检查 List 中的项目是否已正确排序。

于 2014-02-26T14:41:49.000 回答
4

您可以模拟/验证 java.util.Collections.shuffle([]) 方法或调用真正的实现(使用 PowerMockito.doCallRealMethod())。但你不能两者都做。

如果你删除

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

呼叫将被验证并且测试将通过。

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

这段代码对我有用:

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 {
}
于 2013-07-30T07:31:13.080 回答