PowerMock详解
2016-09-04 20:38
387 查看
- 概述
PowerMock有两个重要的注解:@RunWith(PowerMockRunner.class)
@prepareForTest({MyObect.class})
@PrepareForTest注解和@RunWith注解是结合使用的,不要单独使用它们中的任何一个,否则不起作用。当使用
PowerMock去mock静态,final或者私有方法时,需要加上这两个注解。
注意,在你输入@RunWith注解时,Eclipse会自动导入org.powermock.modules.junit4.legacy.PowerMockRunner包,记得把它换成org.powermock.modules.junit4.PowerMockRunner,否则会抛java.lang.NoClassDefFoundError.
- 普通Mock(1)
测试目标代码:public boolean callArgumentInstance(File file) { return file.exists(); }测试用例代码:
@Test public void testCallArgumentInstance() { File file = PowerMockito.mock(File.class); ClassUnderTest underTest = new ClassUnderTest(); PowerMockito.when(file.exists()).thenReturn(true); Assert.assertTrue(underTest.callArgumentInstance(file)); }说明:普通Mock不需要加@RunWith和@PrepareForTest注解。
- 普通Mock(2)
测试目标代码:public String getFilePath() { return path; }
public String getPayloadName() { String pathWithName = getFilePath(); try { int index = pathWithName.lastIndexOf(Constant.SLASH); <span style="white-space:pre"> </span>return pathWithName.substring(index + 1); } catch (Exception e) { <span style="white-space:pre"> </span>return pathWithName; } }
测试用例代码:
@Test public void testGetPayloadName() throws Exception { FileItem item = PowerMockito.mock(FileItem.class); String filePath = "../../../test/updates/Citrix.ibr"; PowerMockito.when(item.getFilePath()).thenReturn(filePath); PowerMockito.when(item, "getPayloadName").thenCallRealMethod(); assertEquals("Citrix.ibr", item.getPayloadName()); }说明:当使用mock出来的对象去调用某个方法时,要对该方法使用thenCallRealMethod().
- whenNew
测试目标代码:public class ClassUnderTest { public boolean callInternalInstance(String path) { File file = new File(path); return file.exists(); } }测试用例代码:
@RunWith(PowerMockRunner.class) @PrepareForTest(ClassUnderTest.class) public class TestClassUnderTest { @Test public void testCallInternalInstance() throws Exception { File file = PowerMockito.mock(File.class); ClassUnderTest underTest = new ClassUnderTest(); PowerMockito.whenNew(File.class).withArguments("bing").thenReturn(file); PowerMockito.when(file.exists()).thenReturn(true); Assert.assertTrue(underTest.callInternalInstance("bing")); } }说明:当使用PowerMockito.whenNew方法时,必须加@PrepareForTest和@RunWith注解。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。
- Mock final方法
测试目标代码:public class ClassUnderTest{ public boolean callFinalMethod(Dependency d){ <span style="white-space:pre"> </span>return d.isAlive(); } } class Dependency{ public final boolean isAlive(){ <span style="white-space:pre"> </span>// do something <span style="white-space:pre"> </span>return true; } }
测试用例代码:
@RunWith(PowerMockRunner.class) public class TestClassUnderTest { @Test @PrepareForTest(Dependency.class) public void testCallFinalMethod() { Dependency depencency = PowerMockito.mock(Dependency.class); ClassUnderTest underTest = new ClassUnderTest(); PowerMockito.when(depencency.isAlive()).thenReturn(true); Assert.assertTrue(underTest.callFinalMethod(depencency)); } }说明: 当需要mock final方法的时候,必须加@PrepareForTest和@RunWith注解,@PrepareForTest里写的类是final方法所在的类。
- Mock私有方法
测试目标代码:public class ClassUnderTest{ public boolean callPrivateMethod(){ <span style="white-space:pre"> </span>return isAlive(); } private boolean isAlive(){ <span style="white-space:pre"> </span>// do something <span style="white-space:pre"> </span>return true; } }测试用例代码:
@RunWith(PowerMockRunner.class) @PrepareForTest(ClassUnderTest.class) public class TestClassUnderTest { @Test public void testCallFinalMethod() { ClassUnderTest underTest = new ClassUnderTest(); <span style="white-space:pre"> </span>PowerMockito.when(underTest.callPrivateMethod().thenCallRealMethod(); PowerMockito.when(underTest, "isAlive").thenReturn(true); Assert.assertTrue(underTest.callPrivateMethod()); } }说明: 和mock final方法一样,必须加@PrepareForTest和@RunWith注解,@PrepareForTest里写的类是private方法所在的类。
- Mock静态方法
测试目标代码:public class ClassUnderTest{ public boolean callStaticMethod(Dependency d){ <span style="white-space:pre"> </span>return Dependency.isExist(); } } class Dependency{ public static boolean isExist(){ <span style="white-space:pre"> </span>// do something <span style="white-space:pre"> </span>return true; } }测试用例代码:
@RunWith(PowerMockRunner.class) public class TestClassUnderTest { @Test @PrepareForTest(Dependency.class) public void testCallFinalMethod() { PowerMockito.mockStatic(Dependency.class); ClassUnderTest underTest = new ClassUnderTest(); PowerMockito.when(Dependency.isExist()).thenReturn(true); Assert.assertTrue(underTest.callStaticMethod(depencency)); } }说明: mock静态方法时需要加@PrepareForTest和@RunWith注解,@PrepareForTest注解中是静态方法所在的类。
- suppress
测试目标代码:public class RefreshMgmt{ private static final String MSG_DOWNLOAD_FAILED = Messages.getString("RefreshThread.0"); public boolean downloadFiles(String path) { return download(path); } private boolean download(String localPath){ <span style="white-space:pre"> </span>// do something <span style="white-space:pre"> </span>return false; } }测试用例代码:
@RunWith(PowerMockRunner.class) @PrepareForTest({ RefreshMgmt.class, Messages.class }) public class TestRefreshMgmt { @Test public void testDownloadFiles() throws Exception { PowerMockito.suppress(PowerMockito.method(Messages.class, "getString", String.class)); <span style="white-space:pre"> </span>//PowerMockito.suppress(PowerMockito.field(RefreshMgmt.class, "MSG_DOWNLOAD_FAILED"); RefreshMgmt mgmt = PowerMockito.mock(RefreshMgmt.class); PowerMockito.when(mgmt, "download", Matchers.anyString()).thenReturn(true); PowerMockito.when(mgmt.downloadFiles(Matchers.anyString())).thenCallRealMethod(); assertTrue(mgmt.downloadFiles("C:/temp")); } }说明: PowerMockito.suppress方法原来禁用某个域或方法,在本例中初始化Messages类会抛出空指针异常,因
此用suppress方法来跳过这个field的初始化。
PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class))表示禁用BaseEntity的构造函数
PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class, String.class, Integer.class))表示禁用参数为String和Integer类型的BaseEntity构造方法。
PowerMockito.suppress(PowerMockito.method(BaseEntity.class, "performAudit", String.class))表示禁用BaseEntity的performAudit方法。
@SuppressStaticInitializationFor("BaseEntity")表示禁用BaseEntity的静态初始化。注意引号部分通常需要全名,比如"com.gitshah.powermock.BaseEntity"。
PowerMockito.suppress(PowerMockito.field(BaseEntity.class,"identifier")):禁用identifier域。
- WhiteBox
测试目标代码:public class CataElement{ private boolean isAvailable = false; private List<FileItem> items = new ArrayList<>(); private Date parseDate(String date) { if(!isAvailable) <span style="white-space:pre"> </span>return null; SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); try { if (date == null || date.isEmpty()) return null; return sdf.parse(date); } catch (ParseException e) { Log.log(Log.WARN, e, getClass()); return null; } } }测试用例代码:
public class CataElementTest{ @Test public void test(){ CataElement e = new CataElement(); Whitebox.setInternalState(e, "isAvailable", true); // other things <span style="white-space:pre"> </span>List<FileItem> items = Whitebox.getInternalState(e, "items"); <span style="white-space:pre"> </span>assertTrue(items.size == 0); } }
Whitebox.setInternalState(object, "fieldName", value)可以设置某个对象的某个field。
Whitebox.getInternalState(object, "fieldName")获取某个对象的某个field的值。
Whitebox.invokeMethod(object, methodName, para)可以调用私有方法,测试私有方法的返回值。
- Answer
测试用例代码:@Test public void test() { final EmployeeService mock = PowerMockito.mock(EmployeeService.class); final Employee employee = new Employee(); PowerMockito.when(mock.findEmployeeByEmail(Matchers.anyString())).then(new Answer<Employee>() { <span style="white-space:pre"> </span>public Employee answer(InvocationOnMock invocation) throws Throwable { <span style="white-space:pre"> </span> final String email = (String) invocation.getArguments()[0]; <span style="white-space:pre"> </span> if(email == null) return null; <span style="white-space:pre"> </span> if(email.startsWith("deep")) return employee; <span style="white-space:pre"> </span> if(email.endsWith("packtpub.com")) return employee; <span style="white-space:pre"> </span> return null; <span style="white-space:pre"> </span>} }); final EmployeeController employeeController = new EmployeeController(mock); assertSame(employee, employeeController.findEmployeeByEmail("deep@gitshah.com")); assertSame(employee, employeeController.findEmployeeByEmail("deep@packtpub.com")); assertNull(employeeController.findEmployeeByEmail("hello@world.com")); }说明:改测试方法根据不同的参数返回不同的结果,Answer的泛型类型必须和answer方法的返回值类型一致。
Answer接口指定执行的action和返回值。Answer的参数是InvocationOnMock的实例,支持:
callRealMethod():调用真正的方法
getArguments():获取所有参数
getMethod():返回mock实例调用的方法
getMock():获取mock实例
相关文章推荐
- 1、使用powermock解决jacoco单测类无法统计覆盖度的问题
- powermock
- TestNG和PowerMock EasyMock的结合
- mock片断2 使用powermock针对private或static写单元测试
- 使用Powermock和mockito
- Mockito: InvalidUseOfMatchersException
- powermock如何阻止静态代码块和调用私有方法
- java.lang.VerifyError 在使用PowerMock EasyMock进行单元测试
- PowerMockito.doReturn().when()与Mockito.when().thenReturn()的区别
- mybatis,mysql,junit,powermock的pom.xml依赖文件配置
- PowerMock - mock静态方法
- Powermock and sonar jacoco的覆盖率不兼容问题解决 1
- Powermock and sonar jacoco的覆盖率不兼容问题解决 2
- Powermock and sonar jacoco的覆盖率不兼容问题解决 3
- 使用Powermock实现单元测试,提高单元测试覆盖率
- PowerMock注解PowerMockIgnore的使用方法
- 兼容机安装ESXi 5.0时PSOD 推荐
- 使用PowerMock模拟静态方法
- The word 'powermock' is not correctly spelled
- 测试用例