java 使用 PowerMock、Mockito 和 TestNG 模拟公共方法中使用的私有方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10524958/
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
Mocking private methods used in public method with PowerMock, Mockito, and TestNG
提问by Thomas
I want to write a unit test for a class I have. This class has a public method, and inside the public method there are calls to private methods in the same class. I want to mock the calls to those private methods. The class is similar to this:
我想为我的课程编写单元测试。这个类有一个公共方法,在公共方法内部调用同一个类中的私有方法。我想模拟对这些私有方法的调用。该类类似于:
public class SomeClass {
public int somePublicMethod(int num) {
int num2 = somePrivateMethod1(num);
int num3 = somePrivateMethod2(num);
return num2 + num3;
}
private int somePrivateMethod1(int num) {
return 2*num;
}
private int somePrivateMethod2(int num) {
return 3*num;
}
}
For my unit test I am trying to use PowerMock with Mockito and TestNG. Here is my attempt at a test that tests somePublicMethod:
对于我的单元测试,我尝试将 PowerMock 与 Mockito 和 TestNG 一起使用。这是我在测试 somePublicMethod 的测试中的尝试:
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.Assert;
import org.testng.annotations.Test;
@PrepareForTest(SomeClass.class)
public class SomeClassTest {
@Test
public void testSomePublicMethod() throws Exception {
int num = 4;
SomeClass someClassSpy = spy(new SomeClass());
doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
doReturn(12).when(someClassSpy, "somePrivateMethod2", num);
int result = someClassSpy.somePublicMethod(num);
Assert.assertEquals(result, 20);
}
}
When I run this test I get an exception and some hints:
当我运行这个测试时,我得到一个异常和一些提示:
FAILED: testSomePublicMethod
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
I've looked at some examples online but I haven't found one that uses PowerMock with Mockito and TestNG specifically to do what I want. Can someone give me some pointers on what I could do differently?
我在网上看过一些例子,但我还没有找到一个专门使用 PowerMock 和 Mockito 和 TestNG 来做我想做的事。有人可以给我一些关于我可以做些什么不同的指示吗?
回答by Tom Tresansky
I don't think this is a problem with PowerMock. It looks like it should work just fine as is. I wonder if there is a problem with TestNG interacting with PowerMock?
我不认为这是 PowerMock 的问题。看起来它应该可以正常工作。我想知道TestNG与PowerMock交互是否有问题?
I have no experience with TestNG, so I tried running the class in JUnit. SomeClass
was left as is, SomeClassTest
was minimally modified to use JUnit:
我没有使用 TestNG 的经验,所以我尝试在 JUnit 中运行该类。 SomeClass
保持原样,SomeClassTest
经过最小程度的修改以使用 JUnit:
import static org.powermock.api.mockito.PowerMockito.*;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {
@Test
public void testSomePublicMethod() throws Exception {
final int num = 4;
final SomeClass someClassSpy = spy(new SomeClass());
doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
doReturn(12).when(someClassSpy, "somePrivateMethod2", num);
final int result = someClassSpy.somePublicMethod(num);
Assert.assertEquals(result, 20);
}
}
The test passes.
测试通过。
Do you need to specify a PowerMockRunner.class
using @RunWIth
or some similar annotation, as with JUnit? If I remove that annotation I recieve the same error message you posted.
您是否需要像 JUnit 一样指定PowerMockRunner.class
using@RunWIth
或一些类似的注释?如果我删除该注释,我会收到与您发布的相同的错误消息。
EDIT:
编辑:
According to this link: http://code.google.com/p/powermock/wiki/TestNG_usage
根据此链接:http: //code.google.com/p/powermock/wiki/TestNG_usage
You need to tell TestNG to use the PowerMock object factory. To do this programmatically, add a method like this to your test class:
您需要告诉 TestNG 使用 PowerMock 对象工厂。要以编程方式执行此操作,请将这样的方法添加到您的测试类中:
@ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
or to be on the safe side you can also extend from the PowerMockTestCase:
或者为了安全起见,您还可以从 PowerMockTestCase 扩展:
@PrepareForTest(SomeClass.class)
public class SomeClassTest extends PowerMockTestCase {
//...
}
回答by nnhthuan
You can't do by that way. Did you try to use reflection?
你不能那样做。您是否尝试使用反射?
By using reflection, you can mock the private methods by mocking the invoke methods, or simpler: you can change it to public temporary, then after the test (maybe in the tearDown) - you can change it back to private.
通过使用反射,您可以通过模拟调用方法来模拟私有方法,或者更简单:您可以将其更改为公共临时,然后在测试之后(可能在拆卸中)-您可以将其更改回私有。
Hope this help.
希望这有帮助。
回答by nnhthuan
I think you are hiting a Mockito limit here. In similar cases, I use Powermock method replacement or, declare the target method as protected and override it when constructing the tested class instance. Hope that helps.
我认为您在这里达到了 Mockito 限制。在类似的情况下,我使用 Powermock 方法替换,或者在构造测试类实例时将目标方法声明为受保护并覆盖它。希望有帮助。