我想为我拥有的类编写一个单元测试。此类具有公共方法,并且在公共方法内部对同一类中的私有方法进行了调用。我想模拟对这些私有方法的调用。该类类似于以下内容:
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;
}
}
对于我的单元测试,我正在尝试将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);
}
}
当我运行此测试时,我得到一个异常和一些提示:
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!
我在网上看过一些例子,但我还没有找到一个专门使用PowerMock和Mockito和TestNG来做我想做的事情的例子。有人可以给我一些关于我可以做些什么不同的事情的指示吗?
我不认为这是PowerMock的问题。 看起来它应该可以正常工作。 我想知道TestNG与PowerMock交互是否存在问题?
我没有使用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);
}
}
测试通过。
您是否需要使用@RunWIth
或类似注释指定PowerMockRunner.class
,就像 JUnit 一样? 如果我删除该注释,则会收到您发布的相同错误消息。
编辑:
根据此链接:http://code.google.com/p/powermock/wiki/TestNG_usage
您需要告诉 TestNG 使用 PowerMock 对象工厂。 若要以编程方式执行此操作,请将如下所示的方法添加到测试类中:
@ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
或者为了安全起见,您也可以从PowerMockTestCase扩展:
@PrepareForTest(SomeClass.class)
public class SomeClassTest extends PowerMockTestCase {
//...
}
那样做。你试过使用反射吗?
通过使用反射,您可以通过模拟 invoke 方法来模拟私有方法,或者更简单:您可以将其更改为公共临时,然后在测试后(可能在 tearDown 中) - 您可以将其更改回私有。
希望这有帮助。
我认为你在这里达到了Mockito的限制。在类似的情况下,我使用 Powermock 方法替换,或者在构造测试类实例时将目标方法声明为受保护并重写它。希望有帮助。