和Mockito一起使用PowerMock
内容
介绍
事实上,PowerMock提供了一个名为“PowerMockito”的类,用于创建mock对象/类并开始验证和期望(一个行为/调用或者返回值),您仍然可以使用Mockito设置和验证期望的所有其他内容(例如times(),anyInt())。
所有的用法需要@RunWith(PowerMockRunner.class)
,并在类上标识@PrepareForTest
注解。
支持版本
PowerMock 2.0.0及更高版本具有Mockito 2的支持。
PowerMock 1.7.0及更高版本具有Mockito 2的实验性支持。
许多问题仍未解决。PowerMock使用Mockito 内部API,但至少可以同时使用两个模拟框架。
Mockito | PowerMock |
---|---|
2.8.9+ | 2.x |
2.8.0-2.8.9 | 1.7.x |
2.7.5 | 1.7.0RC4 |
2.4.0 | 1.7.0RC2 |
2.0.0-beta - 2.0.42-beta | 1.6.5-1.7.0RC |
1.10.8 - 1.10.x | 1.6.2 - 2.0 |
1.9.5-rc1 - 1.9.5 | 1.5.0 - 1.5.6 |
1.9.0-rc1 & 1.9.0 | 1.4.10 - 1.4.12 |
1.8.5 | 1.3.9 - 1.4.9 |
1.8.4 | 1.3.7 & 1.3.8 |
1.8.3 | 1.3.6 |
1.8.1 & 1.8.2 | 1.3.5 |
1.8 | 1.3 |
1.7 | 1.2.5 |
Maven配置
JUnit
TestNG
用法
在下面的示例中,为了更好地了解方法的位置,我们在Mockito或PowerMockito API中未对方法使用静态导入。但是,我们强烈建议您在实际的测试用例中静态导入方法,以提高可读性。
注意:Mockito团队在Mockito 2.1.0中增加了模拟final类/方法的能力。自PowerMock 1.7.0(经过Mockito 2.8.9测试)以来,PowerMock支持此功能。可以使用PowerMock Configuration启用该功能。如果使用Mockito 2,建议使用Mockito模拟final方法/类。
Mock静态方法
如何模拟(mock)和存根(stub):
- 在类上添加
@PrepareForTest
。
@PrepareForTest(Static.class) // Static.class contains static methods
- 调用
PowerMockito.mockStatic()
以Mock静态类(用PowerMockito.spy(class)
mock特定方法):
PowerMockito.mockStatic(Static.class);
- 只需使用Mockito.when()来设置您的期望:
Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);
注意:如果需要模拟java系统类加载器/bootstrap类加载器(在java.lang或java.net等中定义的类)加载的类,则需要使用此方法。
如何验证行为
静态方法的验证分两个步骤进行。
- 首先调用
PowerMockito.verifyStatic(Static.class)
以开始验证行为,然后 - 调用的静态方法
Static.class
进行验证。例如:
PowerMockito.verifyStatic(Static.class); // 1
Static.firstStaticMethod(param); // 2
重要提示:您需要按方法逐个调用verifyStatic(Static.class)
验证。
如何使用参数匹配器
Mockito匹配器可能仍适用于PowerMock mock。例如,对每个mock的静态方法使用自定义参数匹配器:
PowerMockito.verifyStatic(Static.class);
Static.thirdStaticMethod(Mockito.anyInt());
如何验证确切的调用次数
您仍然可以将Mockito.VerificationMode(例如Mockito.times(x))与PowerMockito.verifyStatic(Static.class, Mockito.times(2))
结合使用:
PowerMockito.verifyStatic(Static.class, Mockito.times(1));
如何将静态void方法存根以引发异常
如果不是私有方法:
PowerMockito.doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
StaticService.executeMethod();
请注意,您可以对final类/final方法执行相同的操作:
PowerMockito.doThrow(new ArrayStoreException("Mock error")).when(myFinalMock).myFinalMethod();
对于私有方法,请使用PowerMockito.when,例如:
when(tested, "methodToExpect", argument).thenReturn(myReturnValue);
Mock,存根和验证静态方法的完整示例
@RunWith(PowerMockRunner.class)
@PrepareForTest(Static.class)
public class YourTestCase {
@Test
public void testMethodThatCallsStaticMethod() {
// mock all the static methods in a class called "Static"
PowerMockito.mockStatic(Static.class);
// use Mockito to set up your expectation
Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);
Mockito.when(Static.secondStaticMethod()).thenReturn(123);
// execute your test
classCallStaticMethodObj.execute();
// Different from Mockito, always use PowerMockito.verifyStatic(Class) first
// to start verifying behavior
PowerMockito.verifyStatic(Static.class, Mockito.times(2));
// IMPORTANT: Call the static method you want to verify
Static.firstStaticMethod(param);
// IMPORTANT: You need to call verifyStatic(Class) per method verification,
// so call verifyStatic(Class) again
PowerMockito.verifyStatic(Static.class); // default times is once
// Again call the static method which is being verified
Static.secondStaticMethod();
// Again, remember to call verifyStatic(Class)
PowerMockito.verifyStatic(Static.class, Mockito.never());
// And again call the static method.
Static.thirdStaticMethod();
}
}
部分Mock
您可以通过使用PowerMockito的PowerMockito.spy部分mock方法。请注意(以下内容取自Mockito文档,同样适用于PowerMockito):有时,无法使用标准when(..)
方法对spy()进行打桩(stubbing,存根)。例如:
List list = new LinkedList();
List spy = spy(list);
//这样是不行的:真正的方法spy.get(0)会被调用并抛出IndexOutOfBoundsException异常(这个list仍然是空的)
//when(spy.get(0)).thenReturn("foo");
//你需要用 doReturn() 去打桩
doReturn("foo").when(spy).get(0);
如何验证行为
只需使用Mockito.vertify()进行标准验证:
Mockito.verify(mockObj, times(2)).methodToMock();
如何验证private行为
使用PowerMockito.verifyPrivate(),例如
verifyPrivate(tested).invoke("privateMethodName", argument1);
这也适用于私有静态方法。
如何mock新对象的构造
使用PowerMockito.whenNew,例如
whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));
请注意,您必须准备在测试过程中的用于创建MyClass
新实例中的类,而不是其MyClass
本身。例如,如果正在执行的类称为X,则必须先进行操作@PrepareForTest(X.class)
才能使whenNew
工作:
@RunWith(PowerMockRunner.class)
@PrepareForTest(X.class)
public class XTest {
@Test
public void test() {
whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));
X x = new X();
x.y(); // y is the method doing "new MyClass()"
..
}
}
如何验证新对象的构造
使用PowerMockito.verifyNew,例如
verifyNew(MyClass.class).withNoArguments();
如何使用参数匹配器
如何使用参数匹配器mock:
Mockito.verify(mockObj).methodToMock(Mockito.anyInt());
Spy的完整示例
@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(PartialMockClass.class)
public class YourTestCase {
@Test
public void spyingWithPowerMock() {
PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());
// use Mockito to set up your expectation
Mockito.when(classUnderTest.methodToMock()).thenReturn(value);
// execute your test
classUnderTest.execute();
// Use Mockito.verify() to verify result
Mockito.verify(mockObj, times(2)).methodToMock();
}
}
私有方法部分mock的完整示例
(在PowerMock版本1.3.6+中可用)
@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(PartialMockClass.class)
public class YourTestCase {
@Test
public void privatePartialMockingWithPowerMock() {
PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());
// use PowerMockito to set up your expectation
PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
// execute your test
classUnderTest.execute();
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
}
}
Mockito mock-maker-inline
在PowerMock版本1.7.0中可用
Mockito团队在Mockito 2.1.0中增加了对final类/方法进行mock的支持。通过在src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
中添加包含以下一行的文件,可以在PowerMock中启用此功能 :
mock-maker-inline
PowerMock实现了自己的MockMaker
,这导致与Mockito的mock-maker-inline
不兼容,即使PowerMock只是作为依赖添加而未使用。如果在类路径中存在两个org.mockito.plugins.MockMaker
,则只能使用其中一个,但不确定是哪一个。
但是PowerMock可以将调用委托给另一个MockMaker
,因此无需PowerMock即可运行测试。从PowerMock 1.7.0开始,可以使用PowerMock Configuration进行配置。
该MockMaker
可以通过创建org/powermock/extensions/configuration.properties
文件来配置和设置:
mockito.mock-maker-class=mock-maker-inline
将Mockitomock-maker-inline
与PowerMock结合使用的示例:
github.com/powermock/p…
更多信息
请查看GitHub中的示例源码。也可以参考在Jayway团队博客中PowerMockito的相关博客。