Java中的PowerMock使用实践

 更新时间:2023年12月14日 09:41:08   作者:Terisadeng  
这篇文章主要介绍了Java中的PowerMock使用实践,@PrepareForTest和@RunWith是成对出现的,一般@RunWith(PowerMockRunner.class),@PrepareForTest的值是引用的静态方法或私有方法的类,需要的朋友可以参考下

一、常用注解

@PrepareForTest和@RunWith是成对出现的,一般@RunWith(PowerMockRunner.class),@PrepareForTest的值是引用的静态方法或私有方法的类。

@InjectMocks注解标注的类会被注入所有被@Mock注解标注的类。

@Before注解用于方法,表示在执行@Test注解标注的方法之前执行。

在initMocks()方法中可以执行MockitoAnnotations.initMocks(this);来将@Mock注解修饰的类注入到@InjectMocks修饰的类。

二、实例操作

首先定义三个类,分别是实体类Employee.java,数据操作类EmployeeDao.java,业务逻辑类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)其中涉及到静态方法,因此需要使用@RunWith(PowerMockRunner.class)

@PrepareForTest({ EmployeeDao.class })注解,PrepareForTest的值是静态方法所在的类或接口,否则会报下面的错误:

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注解在调用@Test注解的方法之前进行初始化,比如使用mock(类的Class对象)来创建需要模拟的对象,这样我们就可以假设被模拟的对象已经实现,尽管他其实是一个没有实现类的接口。

3)在模拟对象创建之后,我们就可以使用when(调用模拟对象的方法).thenReturn(定义方法调用的返回值),这样我们就相当于假设调用被模拟对象的方法后返回的一直是thenReturn中定义的值。这样我们就不用关心被模拟对象的实现按,只关心下面我们测试的业务逻辑是否存在问题。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ EmployeeDao.class })
public class EmployeeServiceImplTest {
    @Mock
    public EmployeeDao employeeDao;
    @Mock
    EmployeeServiceImpl employeeServiceImpl;
    // @Before注解的方法会在调用测试方法前执行初始化动作
    @Before
    public void initMocks() {
        // 创建模拟对象EmployeeDao的实例
        employeeDao = mock(EmployeeDao.class);
        // 将模拟对象赋给业务类实例
        employeeServiceImpl = new EmployeeServiceImpl(employeeDao);
    }
    @Test
    public void getEmployeeTest() {
        String name = "scott";
        Employee employee = new Employee();
        employee.setName("scott");
        employee.setSalary(8888.0);
        // 定义当执行employeeDao.getEmployee(name)方法时始终返回employee对象,相当于实现了employeeDao的这个方法
        when(employeeDao.getEmployee(name)).thenReturn(employee);
        /*
         * 下面测试我们想要单元测试的employeeServiceImpl.getEmployee(name)方法 我们已经屏蔽了该方法对employeeDao.getEmployee(name)的调用,相当于解除了依赖
         * 这样我们只需要关心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";
        // 因为这里调用的是静态方法,因此使用PowerMockito.mockStatic(EmployeeDao.class);来模拟静态类
        PowerMockito.mockStatic(EmployeeDao.class);
        // 使用doNothing()定义执行下面一句语句时什么也不做
        PowerMockito.doNothing().when(EmployeeDao.class);
        // 这一句由于上面的doNothing()即使会抛异常也不会再抛
        EmployeeDao.deleteEmployee(name);
        // 因此employeeServiceImpl.deleteEmployee(name)执行时也没有发现异常返回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)执行会返回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()没有生效,原因是这里调用的是实例方法,不是静态方法
        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()实际没有生效,因为这里调用的是实例方法,不是静态方法,因此不存在使下一句语句抛异常的作用
        PowerMockito.doThrow(new NullPointerException()).when(employeeDao).saveEmployee(employee);
        employeeServiceImpl.saveEmployee(employee);
    }
}

到此这篇关于Java中的PowerMock使用实践的文章就介绍到这了,更多相关PowerMock使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java线程之死锁

    java线程之死锁

    这篇文章主要介绍了Java线程之死锁,死锁是这样一种情形-多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止
    2022-05-05
  • Spring Cloud Gateway入门解读

    Spring Cloud Gateway入门解读

    本篇文章主要介绍了Spring Cloud Gateway入门解读,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • 详解Reactor如何优雅Exception异常处理

    详解Reactor如何优雅Exception异常处理

    初识响应式编程的时候,除了从命令式的思维方式转变为函数式的编程方式外,其中有一个很大的不适应的地方就是在面对异常时该怎么处理。本文将通过Project Reactor的文档以及源码来深入解读,在reactor中是如何优雅地实现这异常处理三板斧,希望对大家有所帮助
    2023-02-02
  • java实现随机验证码图片生成

    java实现随机验证码图片生成

    这篇文章主要为大家详细介绍了java实现随机验证码图片生成,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • JAVA反射机制中getClass和class对比分析

    JAVA反射机制中getClass和class对比分析

    这篇文章主要介绍了JAVA反射机制中getClass和class对比分析,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • java之swing表格实现方法

    java之swing表格实现方法

    这篇文章主要介绍了java之swing表格实现方法,以实例形式分析了swing构建表格的方法,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • java面试散列表及树所对应容器类及HashMap冲突解决全面分析

    java面试散列表及树所对应容器类及HashMap冲突解决全面分析

    这篇文章主要介绍了java面试中的java散列表及树所对应容器类与HashMap冲突解决的问题总结,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • RocketMQ消息中间件超详细解读

    RocketMQ消息中间件超详细解读

    这篇文章主要介绍了RocketMQ消息中间件超详细解读,RocketMQ作为一款纯java、分布式、队列模型的开源消息中间件,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等,本文就来详细解读一下,需要的朋友可以参考下
    2023-05-05
  • @MapperScan和@ComponentScan一块使用导致冲突的解决

    @MapperScan和@ComponentScan一块使用导致冲突的解决

    这篇文章主要介绍了@MapperScan和@ComponentScan一块使用导致冲突的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java终止线程的几种方式实例总结

    Java终止线程的几种方式实例总结

    这篇文章主要给大家介绍了关于Java终止线程的几种方式,线程停止即Terminated状态是伴随run方法的结束而生,也就是run完成后由Thread类来决定线程停止了,销毁资源释放空间,下面需要的朋友可以参考下
    2023-06-06

最新评论