背景
由于Mockito的局限性,对final、private、static等方法不能mock,PowerMockito测试框架正好弥补Mockito的不足。
PowerMockito入门
依赖配置
// PowerMock
testCompile 'org.powermock:powermock-module-junit4:1.6.5'
testCompile 'org.powermock:powermock-module-junit4-rule:1.6.5'
testCompile 'org.powermock:powermock-api-mockito:1.6.5'
testCompile 'org.powermock:powermock-classloading-xstream:1.6.5'
PowerMock有三个重要的注解:
@RunWith(PowerMockRunner.class)
@PrepareForTest({YourClassWithEgStaticMethod.class})
@PowerMockIgnore("javax.management.*")
如果你的测试用例里没有使用注解@PrepareForTest,那么可以不用加注解@RunWith(PowerMockRunner.class),反之亦然。当你需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就需要加注解@PrepareForTest。这一点和Mockito的使用方式是类似的,要么使用这种注解的方式
@RunWith(PowerMockRunner.class)
@PrepareForTest({YourClassWithEgStaticMethod.class})
PowerMockito使用
public class ClassUnder {
public boolean callArgumentInstance(File file) {
return file.exists();
}
public boolean callInternalInstance(String path) {
File file = new File(path);
return file.exists();
}
public boolean callFinalMethod(ClassDependency refer) {
return refer.isAlive();
}
public boolean callStaticMethod() {
return ClassDependency.isExist();
}
public boolean callPrivateMethod() {
return isExist();
}
public String callSystemStaticMethod(String str) {
return System.getProperty(str);
}
private boolean isExist() {
return false;
}
}
public class ClassDependency {
public final boolean isAlive() {
// do something
return false;
}
public static boolean isExist() {
// do something
return false;
}
}
测试代码的类体:
public class ClassUnderTest {
private ClassUnder classUnder;
@Before
public void setUp() throws Exception {
classUnder = new ClassUnder();
}
}
普通Mock: Mock参数传递的对象
测试目标方法:callArgumentInstance
测试用例代码:
@Test
public void testCallArgumentInstance() throws Exception {
File file = PowerMockito.mock(File.class);
PowerMockito.when(file.exists()).thenReturn(true);
assertTrue(classUnder.callArgumentInstance(file));
}
说明:普通Mock不需要加@RunWith和@PrepareForTest注解。
Mock方法内部new出来的对象
测试目标方法:callInternalInstance
测试用例代码:
@Test
@PrepareForTest(ClassUnder.class)
public void testCallInternalInstance() throws Exception {
File file = PowerMockito.mock(File.class);
//当内部new一个对象,并且传入的参数是"test",就返回一个File对象。
PowerMockito.whenNew(File.class).withArguments("test").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);
assertTrue(classUnder.callInternalInstance("test"));
}
- 当使用PowerMockito.whenNew方法时,必须加注解@PrepareForTest和@RunWith。
- 注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。
Mock普通对象的final方法
测试目标方法:callFinalMethod
测试用例代码:
@Test
@PrepareForTest(ClassDependency.class)
public void callFinalMethod() throws Exception {
ClassDependency classDependency = PowerMockito.mock(ClassDependency.class);
PowerMockito.when(classDependency.isAlive()).thenReturn(true);
assertTrue(classUnder.callFinalMethod(classDependency));
}
- 当需要mock final方法的时候,必须加注解@PrepareForTest和@RunWith。
- 注解@PrepareForTest里写的类是final方法所在的类。
Mock普通类的静态方法
测试目标方法:callStaticMethod
测试用例代码:
@Test
@PrepareForTest(ClassDependency.class)
public void callStaticMethod() throws Exception {
//mock静态方法所在的类
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
assertTrue(classUnder.callStaticMethod());
}
- 当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith
- 注解@PrepareForTest里写的类是静态方法所在的类。
Mock私有方法
测试目标方法:callPrivateMethod
测试用例代码:
@Test
@PrepareForTest(ClassUnder.class)
public void callPrivateMethod() throws Exception {
//mock 私有方法的类 ClassUnder
ClassUnder under = PowerMockito.mock(ClassUnder.class);
//当执行classUnder.callPrivateMethod()的时候调用它实际的方法。
PowerMockito.when(under.callPrivateMethod()).thenCallRealMethod();
PowerMockito.when(under,"isExist").thenReturn(true);
assertTrue(under.callPrivateMethod());
}
- 和Mock普通方法一样,只是需要加注解@PrepareForTest(ClassUnderTest.class)
- 注解里写的类是私有方法所在的类。
Mock系统类的静态和final方法
测试目标方法:callSystemStaticMethod
测试用例代码:
@Test
@PrepareForTest(ClassUnder.class)
public void callSystemStaticMethod() throws Exception {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
assertEquals("bbb",classUnder.callSystemStaticMethod("aaa"));
}
- 说明:和Mock普通对象的静态方法、final方法一样,只不过注解@PrepareForTest里写的类不一样
- 注解里写的类是需要调用系统方法所在的类