Java 如何使用PowerMockito模拟私有静态方法?

Java 如何使用PowerMockito模拟私有静态方法?,java,unit-testing,mocking,powermockito,Java,Unit Testing,Mocking,Powermockito,不幸的是,被接受的答案对我不起作用。我有一个带有私有方法的静态实用程序类,需要对其进行测试。我发现当我模仿这样的方法时: PowerMockito.spy(StaticUtil.class); PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList); 我得到一个空指针异常,因为实际

不幸的是,被接受的答案对我不起作用。我有一个带有私有方法的静态实用程序类,需要对其进行测试。我发现当我模仿这样的方法时:

PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
我得到一个空指针异常,因为实际上正在调用
getSomethingMethod()
。当我调试时,我看到当我运行我试图测试的方法时它没有被调用,但是当我设置模拟时它正在运行。看起来这就是以这种格式创建模拟时应该发生的事情

因此,我尝试通过以下方式设置模拟:

PowerMockito.spy(StaticUtil.class);        
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);

但是,我从Eclipse中得到一个错误,它说我需要将
getSomethingMethod()
的可见性更改为public。使用PowerMockito的最大好处不是可以模拟私有方法吗?我需要模拟这个
私有静态
方法(在安装过程中不实际调用该方法)。

您必须使用它们在中指定的精确语法。该语法是
doReturn(returnValue)。这里提供的两个示例都没有使用该示例


这里有一些扩展的解释。我创建了一个示例测试框架来演示这一点:

正在尝试在此类上运行测试:

package org.test.stackoverflow;

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

public class StaticUtil {
  public static void Wrapper() {
    getSomethingMethod(null, null, false, Collections.<String>emptyList());
  }

  private static List<String> getSomethingMethod(Object[] obj,
      String[] str, boolean flag, List<String> aList){ 
    System.out.println("I happen!");
    return aList;
  }
}
因此,如果它打印出
I occurrent
,那么我们使用了错误的语法。当我运行此程序时,我们得到:

Beginning Test when(Class klass, String method name).doReturn(result)
I happen!
End Test when
Beginning Test doReturn().when(Class klass, String method name)
End Test doReturn
因此,您必须在第三个测试中使用语法


注意:此示例使用静态空参数;显然,您应该将示例配置为根据您的应用程序正常使用。

当您设置模拟对象的期望值时,必须使用参数匹配器,如matchers.any()或matchers.anyString(),但不能使用实际参数

有关更多详细信息,请参阅我对的回答

存在一个潜在问题:“testDoReturnClassStringMethod”中的语法未正确模拟。 在该方法中,他试图模拟StaticUtil类,但没有调用测试方法包装器。参见示例

@Test
public void testDoReturnClassStringMethod() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList);
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");
}
结果是

Beginning Test doReturn().when(Class klass, String method name
I happen!
End Test doReturn
“我会的!”是印刷的。模拟未正确配置

正确的嘲弄方式是:

@Test
public void testDoReturnWithProperMock() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", Matchers.anyObject(), Matchers.anyObject(), Matchers.anyBoolean(), Matchers.anyList());
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");

}
其结果是:

Beginning Test doReturn().when(Class klass, String method name
End Test doReturn

你能粘贴更多的测试代码吗?您的测试类是否为电源模拟做好了适当的准备?胡猜,您没有
@PrepareForTest
,非常感谢您提供了详细的答案,我花了很长时间在这个问题上!第三个测试中的语法工作得很好。谢谢谢谢谢谢!!第三次测试是如何进行的?'我会的字符串未打印,这并不意味着模拟配置正确。在这里,您试图模拟StaticUtil类,但没有调用测试方法包装器。请参阅我的另一个答案。投票人,请更新投票原因正确答案这是一个仅限边界链接的答案。您应该在此处扩展您的答案,以包含尽可能多的信息,并仅将链接用于参考。它是@kswaughs回答的另一个SO问题的唯一链接答案。要么将相关信息移植到此处,要么将此问题标记为链接问题的副本。@kswaugh您先发布了此答案,然后发布了第二个答案。您可以编辑此(第一个)答案并添加其他信息。请参见答案下方的“编辑”链接。您的链接也只是关于堆栈溢出的另一个答案,如果这回答了这个问题,那么这可能是重复的?看这个问题:)
Beginning Test doReturn().when(Class klass, String method name
End Test doReturn