首页 > 其他 > 详细

单元测试——PowerMock总结

时间:2020-07-26 20:40:58      阅读:93      评论:0      收藏:0      [点我收藏+]

最近项目中单元测试覆盖率要求越来越高,之前Junit和Mock已经无法胜任,所以引入了更强大的PowerMock,方便我们解决静态方法,私有方法等。因此,本文输出PowerMock作为实际使用的小结。

maven项目引入依赖(版本号看实际需要)

 1       <dependency>
 2         <groupId>org.powermock</groupId>
 3         <artifactId>powermock-module-junit4</artifactId>
 4         <version>${powermock.version}</version>
 5         <scope>test</scope>
 6       </dependency>
 7       <dependency>
 8         <groupId>org.powermock</groupId>
 9         <artifactId>powermock-api-mockito</artifactId>
10         <version>${powermock.version}</version>
11         <scope>test</scope>
12       </dependency>

普通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 class UserService {
 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

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
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 
19     public String getEmployeeByName(String name){
20         throw new UnsupportedOperationException();
21     }
22 }

 

普通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 }

 四、参数使用

 4.1 org.mockito.Matchers使用

 1     /**
 2      * org.mockito.Matchers使用:Matchers.anyString()
 3      *
 4      * @RunWith(PowerMockRunner.class)
 5      * @PrepareForTest(EmployeeService.class)
 6      */
 7     @Test
 8     public void getEmployeeByNameTest1() throws Exception {
 9         EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class);
10         PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao);
11         PowerMockito.when(employeeDao.getEmployeeByName(Matchers.anyString())).thenReturn("hello");
12         EmployeeService employeeService = new EmployeeService();
13         employeeService.getEmployeeByName(Matchers.anyString());
14     }

4.2 ArgumentMatcher使用

注意还使用了Matchers.argThat(new MyArgumentMatcher())

    /**
     * ArgumentMatcher使用
     *
     * @RunWith(PowerMockRunner.class)
     * @PrepareForTest(EmployeeService.class)
     */
    @Test
    public void getEmployeeByNameTest2() throws Exception {
        EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class);
        PowerMockito.whenNew(EmployeeDao.class).withNoArguments().thenReturn(employeeDao);
        PowerMockito.when(employeeDao.getEmployeeByName(Matchers.argThat(new MyArgumentMatcher()))).thenReturn("hello");
        EmployeeService service = new EmployeeService();

        Assert.assertEquals("hello", service.getEmployeeByName("selectOne"));
        Assert.assertEquals("hello", service.getEmployeeByName("selectTwo"));
        Assert.assertEquals("hello", service.getEmployeeByName("selectThree"));
        /**
         * 如果采用其他String就会报错,如下:
         * Assert.assertEquals("hello",service.getEmployeeByName("Others"));
         */
    }

    private class MyArgumentMatcher extends ArgumentMatcher<String> {

        @Override
        public boolean matches(Object argument) {
            String value = (String) argument;
            switch (value) {
                case "selectOne":
                case "selectTwo":
                case "selectThree":
                    return true;
                default:
                    return false;
            }
        }
    }

 

单元测试——PowerMock总结

原文:https://www.cnblogs.com/gzhcsu/p/13381161.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!