PowerMock扩展自Mockito,通过Java反射机制解决Mockito的一些问题,比如:在模拟final,static或者private方法上的不足。
1. Maven依赖
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
为了使用PowerMockito,我们需要在被测试类上添加以下两个注解
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")
@PrepareForTest注解中的fullyQualifiedNames代表一组我们想要mock的类的全限定名。在上面的例子中,我们使用了带有通配符的包名,这样,PowerMockito就会准备好com.baeldung.powermockito.introduction包下的所有的类,使他们可以用来mock。
2. 模拟构造器和final方法
本节,我们展示在使用new操作符实例化类时,如何得到一个mock对象,而非真实的对象,并使用mock对象来模拟final方法。
public class CollaboratorWithFinalMethods {
public final String helloMethod() {
return "Hello World!";
}
}
调用无参构造器,返回mock对象
CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);
whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);
CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods();
verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();
调用final方法
when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");
String welcome = collaborator.helloMethod();
Mockito.verify(collaborator).helloMethod();
assertEquals("Hello Baeldung!", welcome);
3. 模拟static方法
public class CollaboratorWithStaticMethods {
public static String firstMethod(String name) {
return "Hello " + name + " !";
}
public static String secondMethod() {
return "Hello no one!";
}
public static String thirdMethod() {
return "Hello no one again!";
}
}
为了模拟static方法,需要使用mockStatic注册类
mockStatic(CollaboratorWithStaticMethods.class);
完整的测试代码如下
@Test(expected = RuntimeException.class)
public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() {
mockStatic(CollaboratorWithStaticMethods.class);
when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString())).thenReturn("Hello Baeldung!");
when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");
when(CollaboratorWithStaticMethods.thirdMethod()).thenThrow(RuntimeException.class);
String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever");
String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");
assertEquals("Hello Baeldung!", firstWelcome);
assertEquals("Hello Baeldung!", secondWelcome);
verifyStatic(times(2));
CollaboratorWithStaticMethods.firstMethod(Mockito.anyString());
verifyStatic(Mockito.never());
CollaboratorWithStaticMethods.secondMethod();
CollaboratorWithStaticMethods.thirdMethod();
}
注意:verifyStatic()要在具体要校验的方法前面
4. 局部校验
public class CollaboratorForPartialMocking {
public static String staticMethod() {
return "Hello Baeldung!";
}
public final String finalMethod() {
return "Hello Baeldung!";
}
private String privateMethod() {
return "Hello Baeldung!";
}
public String privateMethodCaller() {
return privateMethod() + " Welcome to the Java world.";
}
}
4.1 局部模拟static方法
我们使用spy(XXX.class)来局部模拟CollaboratorForPartialMocking类,并为static方法设置预期
spy(CollaboratorForPartialMocking.class);
when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");
校验如下
returnValue = CollaboratorForPartialMocking.staticMethod();
verifyStatic();
CollaboratorForPartialMocking.staticMethod();
assertEquals("I am a static mock method.", returnValue);
4.2 局部模拟final和private方法
我们使用spy(object)来局部模拟CollaboratorForPartialMocking对象
CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking();
CollaboratorForPartialMocking mock = spy(collaborator);
final方法
when(mock.finalMethod()).thenReturn("I am a final mock method.");
returnValue = mock.finalMethod();
verify(mock,times(3)).finalMethod();
assertEquals("I am a final mock method.", returnValue);
private方法
when(mock, "privateMethod").thenReturn("I am a private mock method.");
returnValue = mock.privateMethodCaller();
verifyPrivate(mock).invoke("privateMethod");
assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);
与final方法不同的是,private方法无法直接被调用。PowerMock使用privateMethodCaller作为代理,调用被测试类的private方法。
完整的测试代码如下:
@Test
public void givenPartialMocking_whenUsingPowerMockito_thenCorrect() throws Exception {
String returnValue;
spy(CollaboratorForPartialMocking.class);
when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");
returnValue = CollaboratorForPartialMocking.staticMethod();
verifyStatic();
CollaboratorForPartialMocking.staticMethod();
assertEquals("I am a static mock method.", returnValue);
CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking();
CollaboratorForPartialMocking mock = spy(collaborator);
when(mock.finalMethod()).thenReturn("I am a final mock method.");
returnValue = mock.finalMethod();
verify(mock,times(3)).finalMethod();
assertEquals("I am a final mock method.", returnValue);
when(mock, "privateMethod").thenReturn("I am a private mock method.");
returnValue = mock.privateMethodCaller();
verifyPrivate(mock).invoke("privateMethod");
assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);
}