java 如何使用 PowerMockito 模拟私有静态方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31796736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I mock a private static method with PowerMockito?
提问by user3897392
This is the same question as found here.Unfortunately, the accepted answer isn't working for me. I have a static utility class with private methods that I need to test. I find that when I mock methods like this:
这与此处发现的问题相同。不幸的是,接受的答案对我不起作用。我有一个带有需要测试的私有方法的静态实用程序类。我发现当我模拟这样的方法时:
PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
I'm getting a null pointer exception because the getSomethingMethod()
is actually being called. When I debug, I see that it isn't being called when I run the method I'm trying to test, but it is running when I am setting up the mock. Based on this site,it looks like that is what is supposed to happen when you create the mock in this format.
我收到一个空指针异常,因为getSomethingMethod()
实际上正在调用它。当我调试时,我发现当我运行我试图测试的方法时它没有被调用,但是当我设置模拟时它正在运行。 基于此站点,当您以这种格式创建模拟时,看起来应该会发生这种情况。
So then I try to set up the mock this way:
那么我尝试以这种方式设置模拟:
PowerMockito.spy(StaticUtil.class);
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);
However, I am get an error from Eclipse that says I need to change the visibility of getSomethingMethod()
to public. Isn't one of the big benefits of using PowerMockito that you can mock private methods? I need to mock this private static
method (without actually calling the method during setup).
但是,我收到了来自 Eclipse 的错误消息,提示我需要更改getSomethingMethod()
对公众的可见性。使用 PowerMockito 的一大好处不是可以模拟私有方法吗?我需要模拟这个private static
方法(在安装过程中没有实际调用该方法)。
回答by durron597
You have to use the exact syntaxthat they specify in the answer you linked. That syntax is doReturn(returnValue).when(Class, String, arguments);
. Neither of the examples you've provided here use that example.
您必须使用他们在您链接的答案中指定的确切语法。该语法是. 您在此处提供的示例均未使用该示例。doReturn(returnValue).when(Class, String, arguments);
Here's some extended explanation. I've thrown together a sample test framework to demonstrate this:
这是一些扩展的解释。我整理了一个示例测试框架来演示这一点:
Trying to run tests on this class:
尝试在这个类上运行测试:
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;
}
}
If the method itself gets invoked, we'll see I happen!
. If it doesn't, we won't.
如果方法本身被调用,我们将看到I happen!
. 如果没有,我们就不会。
Then, I use this test class:
然后,我使用这个测试类:
package org.test.stackoverflow;
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.stackoverflow.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");
}
}
So, if it prints I happen
, then we've used the wrong syntax. When I run this program, we get:
所以,如果它打印出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
Therefore, you must use the syntax in the third test.
因此,您必须使用第三个测试中的语法。
Note: this example uses static, empty arguments; obviously you should configure your example to use Argument Matchersas normal as appropriate for your application.
注意:此示例使用静态的空参数;显然,您应该将示例配置为正常使用适合您的应用程序的参数匹配器。
回答by kswaughs
when you set the expectations on mock object, you have to use argument matchers like Matchers.any() or Matchers.anyString() but not actual arguments.
当您在模拟对象上设置期望时,您必须使用参数匹配器,如 Matchers.any() 或 Matchers.anyString() 而不是实际参数。
For more details, see my answer to J-Unit Test: Make static void method in final class throw exception
有关更多详细信息,请参阅我对J-Unit 测试的回答:在最终类中创建静态无效方法抛出异常
There is a potential issue with durron597's answer: the syntax in 'testDoReturnClassStringMethod' is not mocked properly. In that method, he tried to mock StaticUtil class but didn't call the test method wrapper. See the example
durron597 的回答存在一个潜在问题:'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");
}
The result for this is
结果是
Beginning Test doReturn().when(Class klass, String method name
I happen!
End Test doReturn
'I happen!' is printed. mock is not configured properly.
“我发生了!” 被打印。模拟未正确配置。
The correct way of mocking is:
正确的嘲讽方式是:
@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");
}
For which the result is:
结果是:
Beginning Test doReturn().when(Class klass, String method name
End Test doReturn