PowerMock擴(kuò)展自Mockito烤低,通過Java反射機(jī)制解決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喧枷,我們需要在被測試類上添加以下兩個(gè)注解
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")
@PrepareForTest注解中的fullyQualifiedNames代表一組我們想要mock的類的全限定名诗鸭。在上面的例子中,我們使用了帶有通配符的包名对室,這樣模燥,PowerMockito就會準(zhǔn)備好com.baeldung.powermockito.introduction包下的所有的類,使他們可以用來mock掩宜。
2. 模擬構(gòu)造器和final方法
本節(jié)蔫骂,我們展示在使用new操作符實(shí)例化類時(shí),如何得到一個(gè)mock對象牺汤,而非真實(shí)的對象辽旋,并使用mock對象來模擬final方法。
public class CollaboratorWithFinalMethods {
public final String helloMethod() {
return "Hello World!";
}
}
調(diào)用無參構(gòu)造器檐迟,返回mock對象
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注冊類
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()要在具體要校驗(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)來局部模擬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)來局部模擬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方法無法直接被調(diào)用溶其。PowerMock使用privateMethodCaller作為代理,調(diào)用被測試類的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);
}