在安卓中我們常用Junit + Mockito + PowerMock 組合進行測試状植。PowerMock是拓展Mockito,主要是為了解決Mockito 框架不支持mock匿名類、final類津畸、static方法振定、private方法的問題,PowerMock內(nèi)部調(diào)用了Mockito的方法(如:PowerMockito.when()內(nèi)部調(diào)用的是Mockito.when())肉拓。
PowerMock的導入
testImplementation "org.powermock:powermock-module-junit4:1.7.3"
testImplementation "org.powermock:powermock-module-junit4-rule:1.7.3"
testImplementation "org.powermock:powermock-api-mockito2:1.7.3" //注意這里是mockito2
testImplementation "org.powermock:powermock-classloading-xstream:1.7.3"
PowerMock使用
首先我們定義一個Fruit類后频,Banana繼承于它。其中有我們后面需要mock的static暖途、private等方法卑惜。
abstract class Fruit {
private String fruit = "水果";
public String getFruit() {
return fruit;
}
}
public class Banana extends Fruit {
private static String COLOR = "黃色的";
private static String SIZE = "BIG";
private String place = "here";
public Banana() {}
public String getPlace() {
return place;
}
public static final String getColor() {
return COLOR;
}
private static String getSize() {
return SIZE;
}
public String getBananaInfo() {
return flavor() + getColor();
}
private String flavor() {
return "甜甜的";
}
public final boolean isLike() {
return true;
}
private final String getPrice() {
return "10";
}
public String privateFinal() {
return getPrice();
}
}
定義Mock類,:
方法一:
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
public class PowerMockito {
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
}
}
首先使用PowerMock必須在類名上加注@RunWith(PowerMockRunner.class)驻售,在方法上添加注解@PrepareForTest露久,注解@PrepareForTest里寫的是要mock的方法所在的類。@PowerMockIgnore用于忽略mock的類欺栗,"android.*" 忽略android的相關類毫痕,因為我們使用Robolectric處理了;"org.mockito.*"纸巷,"org.robolectric.*" 忽略Mockito和Robolectric的相關類镇草,因為我們不應該mock它們自己眶痰。
方法二:
有時我們會使用多個測試框架瘤旨,可能@RunWith會占用,這時我們可以使用@Rule
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
public class PowerMockito {
@Rule
public PowerMockRule rule = new PowerMockRule();
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
}
}
使用方法總結竖伯,(final)表示final可有可無:
1存哲、Mock public (final):
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
Banana mBanana = PowerMockito.mock(Banana.class);
PowerMockito.when(mBanana.isLike()).thenReturn(false);
Assert.assertFalse(mBanana.isLike());
}
2、Mock public static (final):
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
PowerMockito.mockStatic(Banana.class);
PowerMockito.when(Banana.getColor()).thenReturn("green");
Assert.assertEquals("green", Banana.getColor());
}
3七婴、Mock private (final):
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
Banana banana = PowerMockito.mock(Banana.class);
PowerMockito.when(banana.getBananaInfo()).thenCallRealMethod();
PowerMockito.when(banana, "flavor").thenReturn("苦苦的");
Assert.assertEquals("苦苦的黃色的", banana.getBananaInfo());
}
4祟偷、Mock private static (final): 無法模擬
5、更改類的私有static常量打厘,不能是final:
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
Whitebox.setInternalState(Banana.class, "COLOR", "red");
Assert.assertEquals("red", Banana.getColor());
}
6修肠、跳過私有方法:
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
PowerMockito.suppress(PowerMockito.method(Banana.class, "flavor"));
Assert.assertEquals("null黃色的", mBanana.getBananaInfo());
}
7、更改父類私有變量户盯,不能是final:
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
Banana mBanana = new Banana();
MemberModifier.field(Banana.class, "fruit").set(mBanana, "蔬菜");
Assert.assertEquals("蔬菜", mBanana.getFruit());
}
8嵌施、Mock 構造方法:
@Test
@PrepareForTest({Banana.class})
public void testMethod() throws Exception {
Banana mBanana = PowerMockito.mock(Banana.class);
PowerMockito.when(mBanana.getBananaInfo()).thenReturn("大香蕉");
//如果new新對象,則返回這個上面設置的這個對象
PowerMockito.whenNew(Banana.class).withNoArguments().thenReturn(mBanana);
//new新的對象
Banana newBanana = new Banana();
Assert.assertEquals("大香蕉", newBanana.getBananaInfo());
}