使用PowerMockito和Mockito进行模拟测试,包括静态方法测试,私有方法测试等,以及方法执行的坑或者模拟不成功解决
一 普通spring项目
依赖:这个很重要,不同版本用法也有点区别:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
接下来就是mock测试了,使用完全模拟测试过程,对于需要测试接口中调用的静态,私有方法等,返回自己想要的预期结果,达到测试效果:
这里有几个要点:
测试过程中完全手动mock,不会真实调用或者产生数据
一 mock对象
order = mock(Order.class);
user = mock(User.class);
二 属性注入
将service等类中需要的其他service或者mapper等mock出来,然后分别使用工具类注入,名称保持一致即可
roomTypeService = mock(RoomTypeServiceImpl.class);
ticketComponetService = mock(TicketComponetServiceImpl.class);
hotelMapper = mock(HotelMapper.class);
//注入属性
ReflectionTestUtils.setField(orderService, "hotelGroupMapper", hotelGroupMapper);
ReflectionTestUtils.setField(orderService, "dsUtils", dsUtils);
ReflectionTestUtils.setField(orderService, "orderMapper", orderMapper);
三 静态方法mock
模拟静态方法返回结果需要使用PowerMockit,测试类上必须加注解@PrepareForTest
//account 获取stub
PowerMockito.mockStatic(Account.class);
Mockito.when(Account.get(anyString(), anyString(), anyString(), anyInt())).thenReturn(account);
四 私有方法
私有方法首先需要在类上加入注解,对于要测试的类中的public方法同样有效,比如测试方法中包含一个public方法,可以同样模拟:
@PrepareForTest(ConsumptionServiceImpl.class) //里面写需要模拟私有方法的类class
然后对象不能mock,必须new一个,并且需要用spy处理:
orderService = PowerMockito.spy(new OrderServiceImpl());
接着使用doreturn .when这种形式模式,不能使用先when后return这种,会报错
注意一点,模拟参数要么全部模拟,要么全部自定义,不能混搭
这里有个大坑,如果出现私有方法还是进去执行的情况,很大可能是参数不对,比如你mock的参数是 anyString(),那么你真是测试时候传递的必须是一个String实例,不能是null,否则mock就会失败,我这里之前一直是对象的一个属性,直接new了一个对象传递
所以一直不成功:
比如 方法需要的是user.getId() ,而且你mock的是一个anyInt(),那么真正传递的时候必须给这个user,setId(9527),否则就无法达成预期的模拟效果,所有方法都一样!!
try {
// 方法名,方法参数,必须全部对应,否则报错方法找不到
PowerMockito.doReturn(1).when(orderService, "dateListMinBook",anyString(),anyString(),any(RoomType.class),anyString(),anyString());
PowerMockito.doReturn(ResponseMessage.success().pushData("dateRoomTypeList",new ArrayList<DateRoomType>())).when(orderService, "eachDateNumAndPrice",any(Order.class),any(RoomType.class),anyBoolean(),anyInt(),anyString(),any(User.class));
PowerMockito.doReturn("2000").when(orderService, "getKeeptimeByWxcidAndHotelidAndLevel",anyString(),anyString(),anyString());
PowerMockito.doNothing().when(orderService, "getPayWay",any(),any(),any(),any(),any());
} catch (Exception e) {
e.printStackTrace();
}
五 预期结果
verify :判断方法执行了几次: 确定测试是否通过
例如:verify(userService, times(1)).queryUser(any(anyInt(),anyString(),anyString());
二 springboot项目使用
1 依赖
<!-- S-junit -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.0-beta.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.0-beta.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.0-RC.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.9</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.12.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>4.0.2</version>
<scope>test</scope>
</dependency>
<!-- E-junit -->
2 创建测试基类
/**
* 测试基类,所有子测试类继承此类即可
*/
@PowerMockRunnerDelegate(SpringRunner.class)
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.security.*"}) //忽略一些mock异常
@SpringBootTest
public class TestBase {
}
3 创建特定的测试类
public class HotelControllerTest extends TestBase { //继承基类即可
@Mock
private HotelService hotelService;
private Integer id;
// 加载springContext进行mock测试,真实调用方法,不需要mock步骤
// @Autowired
// private HotelController hotelController;
// 纯mock测试,不加载springContext,执行mock操作,必须mock步骤,不会真实调用
@InjectMocks
private HotelController hotelController=new HotelController();
// 应用到所有门店测试
@Test
public void detailTest(){
System.out.println("test start.....");
// 1 构造参数
ininParams(1);
// 2 mock步骤
mockStep();
// 3 执行操作
ResponseMessage result = hotelController.detail(id);
System.out.println(new Gson().toJson(result));
assertEquals(0, (int) result.getCode());
}
private void mockStep() {
when(hotelService.detail(anyInt())).thenReturn(ResponseMessage.success());
}
private void ininParams(Integer type) {
switch(type){
case 1:
id=17317;
break;
case 2:
id=2;
break;
default:
break;
}
}
}
4 模拟私有方法和静态方法
@PrepareForTest(OrderServiceImpl.class) // 需要调用私有或者静态方法的类
public class OrderControllerTest extends TestBase { private OrderServiceImpl orderServiceImpl; //需要调用私有或者静态方法时,不能使用@Mock,还需要@before初始化属性 @Mock
private OrderMapper orderMapper;
@Mock
private RestTemplateUtil restTemplateUtil;
private Integer orderId;
private String wxcid; @Before
public void init(){
//处理私有方法模拟实例
orderServiceImpl = PowerMockito.spy(new OrderServiceImpl()); //使用spy模拟的需要手动注入属性,因为什么都没有
ReflectionTestUtils.setField(orderController, "iOrderService", orderServiceImpl);
ReflectionTestUtils.setField(orderServiceImpl, "orderMapper", orderMapper);
ReflectionTestUtils.setField(orderServiceImpl, "restTemplateUtil", restTemplateUtil);
} //纯mock测试,不加载springContext,执行mock操作,必须mock步骤,不会真实调用
@InjectMocks
private OrderController orderController=new OrderController(); @Test
public void cancelTest(){
System.out.println("test start.....");
// 1 构造参数
ininParams();
// 2 mock步骤
mockStep();
// 3 执行操作
ResponseMessage cancel = orderController.cancel(wxcid, orderId);
assertEquals(0,(int)cancel.getCode());
} private void mockStep() {
Order order = new Order();
order.setStatus(2);
when(orderMapper.getOrderByOrderId(anyInt())).thenReturn(order);
when(orderMapper.updateStatus(anyInt(),anyInt())).thenReturn(2);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("code",0);
when(restTemplateUtil.postToCri(anyString(),anyString(),any())).thenReturn(jsonObject);
//处理私有方法,必须用这种写法
try {
PowerMockito.doNothing().when(orderServiceImpl, "returnTicketTouser", anyString(),any());
PowerMockito.doReturn(ErrorCode.SUCCESS).when(orderServiceImpl, "refoundAndGetCode", any(),any(),any(),any());
} catch (Exception e) {
e.printStackTrace();
}
} private void ininParams() {
wxcid="57af462dff475fe4644de32f08406aa8";
orderId=25864;
}
}
注意:
如果是分模块项目,springboot项目的启动类只能有一个,即需要把其他service,dao,common模块的启动类的启动注解给注释掉,否则测试启动会报错
使用PowerMockito和Mockito进行模拟测试,包括静态方法测试,私有方法测试等,以及方法执行的坑或者模拟不成功解决的更多相关文章
- Android测试(二):Android测试基础
原文地址:https://developer.android.com/training/testing/fundamentals.html 用户在不同的级别上与你的应用产生交互.从按下按钮到将信息下载 ...
- 《大话移动APP测试:Android与iOS应用测试指南》
<大话移动app测试:android与ios应用测试指南> 基本信息 作者: 陈晔 出版社:清华大学出版社 ISBN:9787302368793 上架时间:2014-7-7 出版日期:20 ...
- Spring MVC测试框架详解——服务端测试
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...
- 专访|HPE测试中心总监徐盛:测试新思维-DevOps,持续测试,更敏捷,更快速
2016年7月22日,「HPE&msup软件技术开放日」将在上海浦东新区,张江高科技园区纳贤路799号科荣大厦小楼2楼举办,msup携手HPE揭秘全球测试中心背后的12条技术实践. 徐盛:HP ...
- SpringMvc测试框架详解----服务端测试
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...
- Web测试要点 做移动端的测试,也做web端的测试,甚至后面桌面端的测试和后台的测试也做了,基本上把我们产品各个端都玩了一轮
Web测试要点 一.功能测试 1.链接测试 (1).测试所有链接是否按指示的那样确实链接到了该链接的页面: (2).测试所链接的页面是否存在: (3).保证Web应用系统上没有孤立的页面(所谓孤立 ...
- iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...
本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...
- Go语言test之类方法测试
Go语言提供了完善的单元测试支持,开发人员可以方便的编写测试代码,保证自己代码的质量.在目前的例子中,一般看到都是普通函数的例子.下面我将通过类方法的单元测试例子来展示一下Go语言的魅力. 首先是代码 ...
- Chrome模拟手机浏览器(iOS/Android)的三种方法,亲测无误!
大网站都有推出自己的手机访问版本页面,不管是新闻类还是视频网站,我们在电脑是无法直接访问到手机网站的,比如我经常访问一个3g.qq.com这个手机站点,如果在电脑上直接打开它,则会跳转到其它页面,一般 ...
随机推荐
- MT【233】染色正方形
有$n$个正方形排成一行,今用红,白,黑三种颜色给这$n$个正方形染色,每个正方形只能染一种颜色.如果要求染白色的正方形必须是偶数个,问有多少种不同的染色方法. 解答:设有$a_n$种不同的染法,则$ ...
- 自学Aruba5.1.1-基于时间的Role定义
点击返回:自学Aruba之路 自学Aruba5.1.1-基于时间的Role定义 可以配置一条rule是基于时间来做限制 具体配置时间(Time ranges)步骤如下: 1 建立一个绝对时间范围,命令 ...
- [luogu4403][bzoj1271][BJWC2008]秦腾与教学评估
题目描述 在秦腾进入北京大学学习的第一个学期,就不幸遇到了前所未有的教学评估.在教学评估期间,同学们被要求八点起床,十一点回宿舍睡觉,不准旷课,上课不准迟到,上课不准睡觉--甚至连著名的北大三角地也在 ...
- Helm使用详解
使用1.helm search 查看charts stable是官方的 local是自己的 2.查看repo helm repo list 3.安装 helm install stable/mysql ...
- 工具函数判断data为整型字符串
/** * 如果data是整型字符串,则转为整型,否则原样返回 * @param {*} data 整型字符串 */ export const stringToInt = (data) => { ...
- react与fetch
JavaScript 中的 ajax 很早之前就有一个诟病----复杂业务下的 callback 嵌套的问题.promise 正是 js 中解决这一问题的钥匙. 接下来我们在react项目中应用到的f ...
- dijkstra(最短路)和Prim(最小生成树)下的堆优化
dijkstra(最短路)和Prim(最小生成树)下的堆优化 最小堆: down(i)[向下调整]:从第k层的点i开始向下操作,第k层的点与第k+1层的点(如果有)进行值大小的判断,如果父节点的值大于 ...
- JAVA分布式架构的演进
系统架构演化历程-初始阶段架构 初始阶段 的小型系统 应用程序.数据库.文件等所有的资源都在一台服务器上通俗称为LAMP 特征:应用程序.数据库.文件等所有的资源都在一台服务器上. 描述:通常服务器操 ...
- CPU密集型和I/O密集型区别
CPU密集型 一些进程绝大多数时间在计算上,称为计算密集型(CPU密集型)computer-bound.一些大量循环的代码(例如:图片处理.视频编码.人工智能等)就是CPU密集型. I/O密集型 有一 ...
- db nosql redis / Redis Sentinel
s Redis基础原理和日常操作方法 http://itsm.cns*****.com/kindeditor/img/20170527/759128afca564051b491e6a51a5bad40 ...