如何使用 PowerMockito 模拟私有静态方法?
How can I mock a private static method with PowerMockito?
This is the same question as found here. 不幸的是,接受的答案对我不起作用。我有一个静态实用程序 class,其中包含我需要测试的私有方法。我发现当我模拟这样的方法时:
PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
我收到一个空指针异常,因为实际上正在调用 getSomethingMethod()
。当我调试时,我发现当我 运行 我试图测试的方法时它没有被调用,但是当我设置模拟时它是 运行ning 。 Based on this site, 以这种格式创建模拟时,看起来应该会发生这种情况。
然后我尝试以这种方式设置模拟:
PowerMockito.spy(StaticUtil.class);
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);
但是,我从 Eclipse 收到一条错误消息,提示我需要将 getSomethingMethod()
的可见性更改为 public。使用 PowerMockito 的一大好处不是可以模拟私有方法吗?我需要模拟此 private static
方法(无需在设置期间实际调用该方法)。
您必须使用他们在 the answer you linked 中指定的 确切语法 。该语法是 doReturn(returnValue).when(Class, String, arguments);
。您在此处提供的两个示例均未使用该示例。
这里有一些扩展说明。我整理了一个示例测试框架来证明这一点:
正在尝试 运行 对此 class 进行测试:
package org.test.Whosebug;
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 happen!
。如果没有,我们不会。
然后,我用这个测试class:
package org.test.Whosebug;
import java.util.List;
import org.junit.runner.RunWith;
import org.junit.*;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(org.test.Whosebug.StaticUtil.class)
public class StaticUtilTest {
Object[] someObjectArray;
String[] someStringArray;
boolean aBoolean;
List<String> someList;
List<String> anotherList;
@Test
public void testWhenClassStringMethod() throws Exception {
System.out.println("Beginning Test when(Class klass, String method name).doReturn(result)");
PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
System.out.println("End Test when");
}
@Test
public void testDoReturnActualMethod() throws Exception {
PowerMockito.spy(StaticUtil.class);
// This doesn't compile as you've correctly stated
// PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod(someObjectArray, someStringArray, aBoolean, someList);
}
@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);
System.out.println("End Test doReturn");
}
}
所以,如果它打印 I happen
,那么我们使用了错误的语法。当我 运行 这个程序时,我们得到:
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
因此,您必须使用第三个测试中的语法。
注意:此示例使用静态空参数;显然,您应该将您的示例配置为根据您的应用程序正常使用 Argument Matchers。
当您在模拟对象上设置期望值时,您必须使用参数匹配器,例如 Matchers.any() 或 Matchers.anyString() 而不是实际参数。
详情请看我对
的回答
存在潜在问题:'testDoReturnClassStringMethod' 中的语法未正确模拟。
在那个方法中,他试图模拟 StaticUtil class 但没有调用测试方法包装器。看例子
@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
'I happen!' 被打印出来。模拟配置不正确。
正确的mock方式是:
@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
This is the same question as found here. 不幸的是,接受的答案对我不起作用。我有一个静态实用程序 class,其中包含我需要测试的私有方法。我发现当我模拟这样的方法时:
PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
我收到一个空指针异常,因为实际上正在调用 getSomethingMethod()
。当我调试时,我发现当我 运行 我试图测试的方法时它没有被调用,但是当我设置模拟时它是 运行ning 。 Based on this site, 以这种格式创建模拟时,看起来应该会发生这种情况。
然后我尝试以这种方式设置模拟:
PowerMockito.spy(StaticUtil.class);
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);
但是,我从 Eclipse 收到一条错误消息,提示我需要将 getSomethingMethod()
的可见性更改为 public。使用 PowerMockito 的一大好处不是可以模拟私有方法吗?我需要模拟此 private static
方法(无需在设置期间实际调用该方法)。
您必须使用他们在 the answer you linked 中指定的 确切语法 。该语法是 doReturn(returnValue).when(Class, String, arguments);
。您在此处提供的两个示例均未使用该示例。
这里有一些扩展说明。我整理了一个示例测试框架来证明这一点:
正在尝试 运行 对此 class 进行测试:
package org.test.Whosebug;
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 happen!
。如果没有,我们不会。
然后,我用这个测试class:
package org.test.Whosebug;
import java.util.List;
import org.junit.runner.RunWith;
import org.junit.*;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(org.test.Whosebug.StaticUtil.class)
public class StaticUtilTest {
Object[] someObjectArray;
String[] someStringArray;
boolean aBoolean;
List<String> someList;
List<String> anotherList;
@Test
public void testWhenClassStringMethod() throws Exception {
System.out.println("Beginning Test when(Class klass, String method name).doReturn(result)");
PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
System.out.println("End Test when");
}
@Test
public void testDoReturnActualMethod() throws Exception {
PowerMockito.spy(StaticUtil.class);
// This doesn't compile as you've correctly stated
// PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod(someObjectArray, someStringArray, aBoolean, someList);
}
@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);
System.out.println("End Test doReturn");
}
}
所以,如果它打印 I happen
,那么我们使用了错误的语法。当我 运行 这个程序时,我们得到:
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
因此,您必须使用第三个测试中的语法。
注意:此示例使用静态空参数;显然,您应该将您的示例配置为根据您的应用程序正常使用 Argument Matchers。
当您在模拟对象上设置期望值时,您必须使用参数匹配器,例如 Matchers.any() 或 Matchers.anyString() 而不是实际参数。
详情请看我对
@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
'I happen!' 被打印出来。模拟配置不正确。
正确的mock方式是:
@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