Java中的PowerMock使用實踐
一、常用注解
@PrepareForTest和@RunWith是成對出現(xiàn)的,一般@RunWith(PowerMockRunner.class),@PrepareForTest的值是引用的靜態(tài)方法或私有方法的類。
@InjectMocks注解標注的類會被注入所有被@Mock注解標注的類。
@Before注解用于方法,表示在執(zhí)行@Test注解標注的方法之前執(zhí)行。
在initMocks()方法中可以執(zhí)行MockitoAnnotations.initMocks(this);來將@Mock注解修飾的類注入到@InjectMocks修飾的類。
二、實例操作
首先定義三個類,分別是實體類Employee.java,數(shù)據(jù)操作類EmployeeDao.java,業(yè)務邏輯類EmployeeService.java,下面是3個類的具體定義:
public class Employee { private String name; private Double salary; /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the salary */ public Double getSalary() { return salary; } /** * @param salary the salary to set */ public void setSalary(Double salary) { this.salary = salary; } }
EmployeeDao.java:
public interface EmployeeDao { public Employee getEmployee(String name); public boolean updateEmployee(Employee employee); public static void deleteEmployee(String name) { throw new NullPointerException(); } public Exception saveEmployee(Employee employee); }
EmployeeService.java:
public class EmployeeServiceImpl { private EmployeeDao employeeDao; public EmployeeServiceImpl() { } public EmployeeServiceImpl(EmployeeDao employeeDao) { this.employeeDao = employeeDao; } public Employee getEmployee(String name) { return employeeDao.getEmployee(name); } public boolean updateEmployee(Employee employee) { return employeeDao.updateEmployee(employee); } public boolean deleteEmployee(String name) { try { EmployeeDao.deleteEmployee(name); return true; } catch (Exception e) { return false; } } public boolean saveEmployee(Employee employee) { try { employeeDao.saveEmployee(employee); return true; } catch (Exception e) { e.printStackTrace(); return false; } } }
PowerMockito知識點
下面是測試類中涉及到的PowerMockito知識點:
1)其中涉及到靜態(tài)方法,因此需要使用@RunWith(PowerMockRunner.class)
@PrepareForTest({ EmployeeDao.class })注解,PrepareForTest的值是靜態(tài)方法所在的類或接口,否則會報下面的錯誤:
org.powermock.api.mockito.ClassNotPreparedException: The class mock.EmployeeDao not prepared for test. To prepare this class, add class to the '@PrepareForTest' annotation. In case if you don't use this annotation, add the annotation on class or method level. at org.powermock.api.mockito.expectation.reporter.MockitoPowerMockReporter.classNotPrepared(MockitoPowerMockReporter.java:32)
2)使用@Before注解在調(diào)用@Test注解的方法之前進行初始化,比如使用mock(類的Class對象)來創(chuàng)建需要模擬的對象,這樣我們就可以假設被模擬的對象已經(jīng)實現(xiàn),盡管他其實是一個沒有實現(xiàn)類的接口。
3)在模擬對象創(chuàng)建之后,我們就可以使用when(調(diào)用模擬對象的方法).thenReturn(定義方法調(diào)用的返回值),這樣我們就相當于假設調(diào)用被模擬對象的方法后返回的一直是thenReturn中定義的值。這樣我們就不用關心被模擬對象的實現(xiàn)按,只關心下面我們測試的業(yè)務邏輯是否存在問題。
@RunWith(PowerMockRunner.class) @PrepareForTest({ EmployeeDao.class }) public class EmployeeServiceImplTest { @Mock public EmployeeDao employeeDao; @Mock EmployeeServiceImpl employeeServiceImpl; // @Before注解的方法會在調(diào)用測試方法前執(zhí)行初始化動作 @Before public void initMocks() { // 創(chuàng)建模擬對象EmployeeDao的實例 employeeDao = mock(EmployeeDao.class); // 將模擬對象賦給業(yè)務類實例 employeeServiceImpl = new EmployeeServiceImpl(employeeDao); } @Test public void getEmployeeTest() { String name = "scott"; Employee employee = new Employee(); employee.setName("scott"); employee.setSalary(8888.0); // 定義當執(zhí)行employeeDao.getEmployee(name)方法時始終返回employee對象,相當于實現(xiàn)了employeeDao的這個方法 when(employeeDao.getEmployee(name)).thenReturn(employee); /* * 下面測試我們想要單元測試的employeeServiceImpl.getEmployee(name)方法 我們已經(jīng)屏蔽了該方法對employeeDao.getEmployee(name)的調(diào)用,相當于解除了依賴 * 這樣我們只需要關心employeeServiceImpl.getEmployee(name)方法的邏輯是否存在問題 */ Employee employee2 = employeeServiceImpl.getEmployee(name); System.out.println(employee2.getSalary()); } @Test public void updateEmployeeTest() { Employee employee = new Employee(); employee.setName("tiger"); employee.setSalary(99999.0); when(employeeDao.updateEmployee(anyObject())).thenReturn(true); Employee employee2 = new Employee(); employee.setName("scott"); employee.setSalary(99999.0); Boolean boolean1 = employeeServiceImpl.updateEmployee(employee2); System.out.println(boolean1); } @Test public void deleteEmployeeTest() { String name = "haha"; // 因為這里調(diào)用的是靜態(tài)方法,因此使用PowerMockito.mockStatic(EmployeeDao.class);來模擬靜態(tài)類 PowerMockito.mockStatic(EmployeeDao.class); // 使用doNothing()定義執(zhí)行下面一句語句時什么也不做 PowerMockito.doNothing().when(EmployeeDao.class); // 這一句由于上面的doNothing()即使會拋異常也不會再拋 EmployeeDao.deleteEmployee(name); // 因此employeeServiceImpl.deleteEmployee(name)執(zhí)行時也沒有發(fā)現(xiàn)異常返回true EmployeeServiceImpl employeeServiceImpl = new EmployeeServiceImpl(); Assert.assertTrue(employeeServiceImpl.deleteEmployee(name)); } @Test public void throwDeleteExceptionTest() { String name = "haha"; PowerMockito.mockStatic(EmployeeDao.class); // doThrow()定義下面一句語句會拋出異常 PowerMockito.doThrow(new NullPointerException()).when(EmployeeDao.class); EmployeeDao.deleteEmployee(name); // 因此employeeServiceImpl.deleteEmployee(name)執(zhí)行會返回false EmployeeServiceImpl employeeServiceImpl = new EmployeeServiceImpl(); assertTrue(employeeServiceImpl.deleteEmployee(name)); } @Test public void saveEmployeeTest() { Employee employee = new Employee(); employee.setName("scott"); employee.setSalary(8888.0); // 打樁,定義方法返回的值 when(employeeDao.saveEmployee(employee)).thenReturn(new NullPointerException()); // 這里doNothing()沒有生效,原因是這里調(diào)用的是實例方法,不是靜態(tài)方法 PowerMockito.doNothing().when(employeeDao).saveEmployee(employee); employeeServiceImpl.saveEmployee(employee); } @Test public void throwSaveEmployeeTest() { Employee employee = new Employee(); employee.setName("scott"); employee.setSalary(8888.0); when(employeeDao.saveEmployee(employee)).thenReturn(new NullPointerException()); // 這里的doThrow()實際沒有生效,因為這里調(diào)用的是實例方法,不是靜態(tài)方法,因此不存在使下一句語句拋異常的作用 PowerMockito.doThrow(new NullPointerException()).when(employeeDao).saveEmployee(employee); employeeServiceImpl.saveEmployee(employee); } }
到此這篇關于Java中的PowerMock使用實踐的文章就介紹到這了,更多相關PowerMock使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
eclipse導入IntelliJ IDEA的maven項目的示例
本篇文章主要介紹了eclipse導入IntelliJ IDEA的maven項目的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12詳解Springboot Oauth2 Server搭建Oauth2認證服務
這篇文章主要介紹了Springboot Oauth2 Server 搭建Oauth2認證服務,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05Spring Security組件一鍵接入驗證碼登錄和小程序登錄的詳細過程
這篇文章主要介紹了Spring Security 一鍵接入驗證碼登錄和小程序登錄,簡單介紹一下這個插件包的相關知識,本文結合示例代碼給大家介紹的非常詳細,需要的朋友參考下吧2022-04-04SpringCloud Gateway的路由,過濾器和限流解讀
這篇文章主要介紹了SpringCloud Gateway的路由,過濾器和限流解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Java構造函數(shù)里的一些坑記錄super()和this()
這篇文章主要介紹了Java構造函數(shù)里的一些坑記錄super()和this(),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03