PowerMock擴(kuò)展自Mockito,通過(guò)Java反射機(jī)制解決Mockito的一些問(wèn)題,比如:在模擬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,我們需要在被測(cè)試類上添加以下兩個(gè)注解
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")
@PrepareForTest注解中的fullyQualifiedNames代表一組我們想要mock的類的全限定名。在上面的例子中,我們使用了帶有通配符的包名,這樣,PowerMockito就會(huì)準(zhǔn)備好com.baeldung.powermockito.introduction包下的所有的類,使他們可以用來(lái)mock。
2. 模擬構(gòu)造器和final方法
本節(jié),我們展示在使用new操作符實(shí)例化類時(shí),如何得到一個(gè)mock對(duì)象,而非真實(shí)的對(duì)象,并使用mock對(duì)象來(lái)模擬final方法。
public class CollaboratorWithFinalMethods {
public final String helloMethod() {
return "Hello World!";
}
}
調(diào)用無(wú)參構(gòu)造器,返回mock對(duì)象
CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);
whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);
CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods();
verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();
調(diào)用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注冊(cè)類
mockStatic(CollaboratorWithStaticMethods.class);
完整的測(cè)試代碼如下
@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()要在具體要校驗(yàn)的方法前面
4. 局部校驗(yàn)
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)來(lái)局部模擬CollaboratorForPartialMocking類,并為static方法設(shè)置預(yù)期
spy(CollaboratorForPartialMocking.class);
when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");
校驗(yàn)如下
returnValue = CollaboratorForPartialMocking.staticMethod();
verifyStatic();
CollaboratorForPartialMocking.staticMethod();
assertEquals("I am a static mock method.", returnValue);
4.2 局部模擬final和private方法
我們使用spy(object)來(lái)局部模擬CollaboratorForPartialMocking對(duì)象
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方法無(wú)法直接被調(diào)用。PowerMock使用privateMethodCaller作為代理,調(diào)用被測(cè)試類的private方法。
完整的測(cè)試代碼如下:
@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);
}