一 为什么需要模拟测试单元框架
1 实际工作中会出现当对某个功能单元测试时,需要依赖其他服务,而这些服务例如第三方接口(发短信接口,支付接口),中间件(redis,消息队列,数据库等),微服务架构项目服务间相互依赖。当碰到依赖不能用或用依赖服务需要消耗大量资源时,使用模拟测试框架轻松解决,解决思路是构建服务返回结果,再执行完整的功能,断言实际结果与期望的。
2 使用单元测试框架,降低bug的出现,提前发现问题。工作中要养成这种良好的习惯。
二 常用的单元模拟测试框架Mockito、Jmock、easyMock。这次介绍能够在实际中解决更多问题的PowerMock。
三 PowerMock简介
官网简介 PowerMock 是一个框架,它扩展了其他模拟库,例如具有更强大的功能的 EasyMock。PowerMock 使用自定义类加载器和字节码操作来模拟静态方法、构造函数、最终类和方法、私有方法、静态初始化器的删除等。通过使用自定义类加载器,无需对 IDE 或持续集成服务器进行任何更改,从而简化了采用。熟悉受支持的模拟框架的开发人员会发现 PowerMock 易于使用,因为整个预期 API 是相同的,无论是静态方法还是构造函数。PowerMock 旨在使用少量方法和注释扩展现有 API,已启用额外功能。目前 PowerMock 支持 EasyMock 和 Mockito。
个人理解 PowerMock是为了解决现有的一些测试框架不能解决的问题,PowerMock可以对final修饰的类和方法,静态属性和方法,私有属性和方法进行测试。其他框架如EasyMock和Mockito目前是没有这些功能。
四 PowerMock优势
1 PowerMock 易于使用。
2 更全面地进行单元测试。
3 简单模拟一些复杂的依赖。
五 开启PowerMock入门介绍
1 下面的demo用到jar依赖如下
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
2 被测试类如下
public class OrderDao {
public int save(){
throw new RuntimeException("数据连接不上了");
}
}
public class OrderService {
private OrderDao orderDao;
public OrderService(OrderDao orderDao) {
this.orderDao = orderDao;
}
public int save(){
orderDao.save();
return 1;
}
}
3 测试类如下。
3.1 当运行时测试是抛异常中断执行,实际工作中经常碰到。有时需要比较长时间才能恢复。那么此时用powerMock就可以快速解决,模拟数据库数据返回,请看3.2。
package powerMock;
import org.junit.Test;
public class TestOrderService {
@Test
public void testSave(){
OrderDao orderDao= new OrderDao();
OrderService orderService=new OrderService(orderDao);
orderService.save();
}
}
3.2 使用powerMock构建出OrderDao实例,指定返回值,其实就是绕过数据库,构造成功执行结果, 再运行测试通过。
package powerMock;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;
import static org.junit.Assert.assertEquals;
public class TestOrderService {
@Test
public void testSave(){
OrderDao orderDao= new OrderDao();
OrderService orderService=new OrderService(orderDao);
orderService.save();
}
@Test
public void testSaveForPowerMock(){
OrderDao orderDao=PowerMockito.mock(OrderDao.class);
PowerMockito.when(orderDao.save()).thenReturn(11);
OrderService orderService=new OrderService(orderDao);
int total=orderService.save();
assertEquals(11, total);
}
}