【问题标题】:Static mocking with PowerMock and Mockito not working使用 PowerMock 和 Mockito 进行静态模拟不起作用
【发布时间】:2013-07-30 05:35:36
【问题描述】:

我正在尝试验证 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));
    }
}

【问题讨论】:

  • 如果您将匹配器的限制从anyListOf 放松到any(List.class),会发生什么?如果将ClassToTest 添加到@PrepareForTest 注释会发生什么?

标签: java unit-testing junit mockito powermock


【解决方案1】:

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

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 中的项目是否已正确排序。

【讨论】:

  • 感谢您的回答!由于当时缺乏经验,我可能正在做一些愚蠢的事情。我完全同意最好测试公共合同而不是内部实施细节。
【解决方案2】:

您可以模拟/验证 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 {
}

【讨论】:

  • 我尝试了你的建议,但我的测试仍然失败,说与模拟的交互为零。查看我的编辑。
  • 啊,谢谢...我错过了我必须调用 Collections.shuffle() 的部分...虽然我可以发誓我也尝试过。
猜你喜欢
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多