單元測試——PowerMock總結
阿新 • • 發佈:2020-07-26
最近專案中單元測試覆蓋率要求越來越高,之前Junit和Mock已經無法勝任,所以引入了更強大的PowerMock,方便我們解決靜態方法,私有方法等。因此,本文輸出PowerMock作為實際使用的小結。
普通POJO
public class User { private String name; private String password; }
普通Dao
1 public class UserDao { 2 3 public int getCount(){ 4 throw new UnsupportedOperationException();5 } 6 7 public void saveUser(User user){ 8 throw new UnsupportedOperationException(); 9 } 10 11 /** 12 * 靜態方法 13 */ 14 public static int removeUser(User user){ 15 throw new UnsupportedOperationException(); 16 } 17 18 }
普通Service
1 public classUserService { 2 3 private UserDao userDao; 4 5 public UserService(UserDao userDao) { 6 this.userDao = userDao; 7 } 8 9 public int getUserCount() { 10 return userDao.getCount(); 11 } 12 13 public void saveUser(User user) { 14 userDao.saveUser(user);15 } 16 17 /** 18 * 呼叫了靜態方法 19 */ 20 public int removeUser(User user) { 21 return UserDao.removeUser(user); 22 } 23 24 }
一、針對普通方法的測試
(1)有參返回——Mock和PowerMock都能處理
1 public class UserServiceTest { 2 3 @Test 4 public void getUserCountwithMockito() { 5 UserDao userDao = Mockito.mock(UserDao.class); 6 Mockito.when(userDao.getCount()).thenReturn(10); 7 UserService userService = new UserService(userDao); 8 int resutl = userService.getUserCount(); 9 Assert.assertEquals(10, resutl); 10 Mockito.verify(userDao, Mockito.times(1)).getCount(); 11 } 12 13 @Test 14 public void getUserCountwithPowerMockito() { 15 UserDao userDao = PowerMockito.mock(UserDao.class); 16 PowerMockito.when(userDao.getCount()).thenReturn(5); 17 UserService userService = new UserService(userDao); 18 int resutl = userService.getUserCount(); 19 Assert.assertEquals(5, resutl); 20 } 21 22 }
(2)無參返回——Mock和PowerMock都能處理
1 public class UserServiceTest { 2 3 @Test 4 public void saveUserwithMock() { 5 // User user = Mockito.mock(User.class); 6 User user = new User(); 7 UserDao userDao = Mockito.mock(UserDao.class); 8 Mockito.doNothing().when(userDao).saveUser(user); 9 UserService userSerivce = new UserService(userDao); 10 userSerivce.saveUser(user); 11 Mockito.verify(userDao, Mockito.times(1)).saveUser(user); 12 } 13 14 15 @Test 16 public void saveUserwithPowerMock() { 17 // User user = new User(); 18 User user = PowerMockito.mock(User.class); 19 UserDao userDao = PowerMockito.mock(UserDao.class); 20 PowerMockito.doNothing().when(userDao).saveUser(user); 21 UserService userService = new UserService(userDao); 22 userService.saveUser(user); 23 24 } 25 26 }
二、針對靜態方法——只能用PowerMock處理了
當呼叫UserDao的靜態方法時,通過@PrepareForTest註解提前準備好一個UserDao類。
1 @RunWith(PowerMockRunner.class) 2 @PrepareForTest({UserDao.class}) 3 public class UserServiceTest { 4 /** 5 * 處理靜態方法-PowerMock,在類上新增兩個註解: 7 * @RunWith(PowerMockRunner.class) 8 * @PrepareForTest(UserDao.class) 9 */ 10 @Test 11 public void removeUserwithPowerMock() { 12 User user = PowerMockito.mock(User.class); 13 PowerMockito.mockStatic(UserDao.class); 14 PowerMockito.when(UserDao.removeUser(user)).thenReturn(1); 15 UserService userService = new UserService(new UserDao()); 16 int result = userService.removeUser(user); 17 Assert.assertEquals(1, result); 18 } 19 }
三、區域性變數——只能用PowerMock處理了
普通POJO
public class Employee { private String name; private String password; }
普通Dao
1 public class EmployeeDao { 2 3 public int getTotalCount(Employee employee) { 4 throw new UnsupportedOperationException(); 5 } 6 7 public void creatEmployee(Employee employee) { 8 throw new UnsupportedOperationException(); 9 } 10 11 public void updateEmployee(Employee employee) { 12 throw new UnsupportedOperationException(); 13 } 14 15 public int getEmployeeCount(Employee employee) { 16 throw new UnsupportedOperationException(); 17 } 18 }
普通Service
1 public class EmployeeService { 2 3 /** 4 * 區域性變數:內部無參構造建立物件,整個方法有返回值 5 */ 6 public int getTotalCount(Employee employee) { 7 EmployeeDao employeeDao = new EmployeeDao(); 8 return employeeDao.getTotalCount(employee); 9 } 10 /** 11 * 區域性變數:內部無參構造建立物件,整個方法無返回值 12 */ 13 public void createEmployee(Employee employee) { 14 EmployeeDao employeeDao = new EmployeeDao(); 15 employeeDao.creatEmployee(employee); 16 } 17 18 /** 19 * 方法內有分支 20 */ 21 public void saveOrUpdate(Employee employee){ 22 EmployeeDao employeeDao = new EmployeeDao(); 23 int count = employeeDao.getEmployeeCount(employee); 24 if(count>0){ 25 employeeDao.updateEmployee(employee); 26 }else{ 27 employeeDao.creatEmployee(employee); 28 } 29 } 30 }
3.1 測試“有返回值”
@PrepareForTest(EmployeeService.class):讓創建出來的EmployeeService例項,採用事先準備好的(@PrepareForTest幫助實現,底層通過改變位元組碼)。
PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao):利用PowerMockito建立無參構造類的例項(通過mock已經準備,如PowerMockito.mock(Employee.class)
),其中 withNoArguments()會拋異常,需要try...catch處理。
建構函式說明
(1)PowerMockito.whenNew(EmployeeDao.class).withNoArguments()
(2)PowerMockito.whenNew(EmployeeDao.class).withAnyArguments()
(3)PowerMockito.whenNew(EmployeeDao.class).withArguments(Object firstArgument, Object... additionalArguments)
1 @RunWith(PowerMockRunner.class) 2 @PrepareForTest(EmployeeService.class) 3 public class EmployeeServiceTest { 4 5 /** 6 * 測試有返回值,在類上新增兩個註解: 7 * 8 * @RunWith(PowerMockRunner.class) 9 * @PrepareForTest(EmployeeService.class) 10 */ 11 @Test 12 public void getTotalCountTest() { 13 Employee employee = PowerMockito.mock(Employee.class); 14 EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class); 15 try { 16 PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao); 17 PowerMockito.when(employeeDao.getTotalCount(employee)).thenReturn(5); 18 EmployeeService employeeService = new EmployeeService(); 19 int totalCount = employeeService.getTotalCount(employee); 20 Assert.assertEquals(5, totalCount); 21 } catch (Exception e) { 22 fail("測試失敗..."); 23 } 24 } 25 }
3.2 測試無返回值
PowerMockito.doNothing().when(employeeDao).creatEmployee(employee);
1 @RunWith(PowerMockRunner.class) 2 @PrepareForTest(EmployeeService.class) 3 public class EmployeeServiceTest { 4 /** 5 * 測試無返回值,在類上新增兩個註解: 6 * 7 * @RunWith(PowerMockRunner.class) 8 * @PrepareForTest(EmployeeService.class) 9 */ 10 @Test 11 public void creatEmplyeeTest() { 12 Employee employee = PowerMockito.mock(Employee.class); 13 14 EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class); 15 try { 16 PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao); 17 PowerMockito.doNothing().when(employeeDao).creatEmployee(employee); 18 EmployeeService employeeService = new EmployeeService(); 19 employeeService.createEmployee(employee); 20 Mockito.verify(employeeDao, Mockito.times(1)).creatEmployee(employee); 21 } catch (Exception e) { 22 fail("測試失敗..."); 23 } 24 } 25 }
3.3 通過Mockito.verify驗證分支
通過PowerMockito.when(employeeDao.getEmployeeCount(employee)).thenReturn(0):中thenReturn的返回值可以走向不同的分支。
1 @RunWith(PowerMockRunner.class) 2 @PrepareForTest(EmployeeService.class) 3 public class EmployeeServiceTest { 4 /** 5 * 測試分支及Mockito.verify,在類上新增兩個註解: 6 * 7 * @RunWith(PowerMockRunner.class) 8 * @PrepareForTest(EmployeeService.class) 9 */ 10 @Test 11 public void saveOrUpdateTest1() { 12 Employee employee = PowerMockito.mock(Employee.class); 13 EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class); 14 try { 15 16 PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao); 17 PowerMockito.when(employeeDao.getEmployeeCount(employee)).thenReturn(0); 18 19 EmployeeService employeeService = new EmployeeService(); 20 employeeService.saveOrUpdate(employee); 21 22 Mockito.verify(employeeDao).creatEmployee(employee); 23 Mockito.verify(employeeDao, Mockito.never()).updateEmployee(employee); 24 } catch (Exception e) { 25 fail("測試失敗..."); 26 } 27 } 28 29 /** 30 * 測試分支及Mockito.verify,在類上新增兩個註解: 31 * 32 * @RunWith(PowerMockRunner.class) 33 * @PrepareForTest(EmployeeService.class) 34 */ 35 @Test 36 public void saveOrUpdateTest2() { 37 Employee employee = PowerMockito.mock(Employee.class); 38 EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class); 39 try { 40 41 PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao); 42 PowerMockito.when(employeeDao.getEmployeeCount(employee)).thenReturn(1); 43 44 EmployeeService employeeService = new EmployeeService(); 45 employeeService.saveOrUpdate(employee); 46 47 Mockito.verify(employeeDao, Mockito.never()).creatEmployee(employee); 48 Mockito.verify(employeeDao).updateEmployee(employee); 49 } catch (Exception e) { 50 fail("測試失敗..."); 51 } 52 } 53 }