框架Mockito
一、什么是mock测试,什么是mock对象?
先来看看下面这个示例:
从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。
一种替代方案就是使用mocks
从图中可以清晰的看出
mock对象就是在调试期间用来作为真实对象的替代品。
mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。
二、什么是Mockito
Mockito是一个针对Java的mocking框架。它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。
官方网站:http://code.google.com/p/mockito/
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency>
java类里要引入
三、Stub和Mock
相同点:Stub和Mock对象都是用来模拟外部依赖,使我们能控制。
不同点:而stub完全是模拟一个外部依赖,用来提供测试时所需要的测试数据。而mock对象用来判断测试是否能通过,也就是用来验证测试中依赖对象间的交互能否达到预期。在mocking框架中mock对象可以同时作为stub和mock对象使用,两者并没有严格区别。 更多信息:http://martinfowler.com/articles/mocksArentStubs.html
四、mockito入门实例
1.1、模拟对象
// 模拟LinkedList 的对象
LinkedList mockedList = Mockito.mock(LinkedList.class);
// 此时调用get方法,是会返回null,因为还没有对方法调用的返回值做模拟
System.out.println(mockedList.get(999));
1.2、模拟方法调用的返回值
// 模拟获取第一个元素时,返回字符串first
Mockito.when(mockedList.get(0)).thenReturn("first");
// 此时打印输出first
System.out.println(mockedList.get(0));
1.3、模拟方法调用抛出异常
Mockito.doThrow(new RuntimeException()).when(mockedList).clear();
1.4、模拟方法调用的参数匹配
Matchers类内加你有很多参数匹配器 anyInt、anyString、anyMap.....Mockito类继承于Matchers,Stubbing时使用内建参数匹配器。例如anyint()如下:
1.5、验证方法调用次数
示例二(web中的3层中的针对某一层的测试):
以前没接触过Mock类型的框架,比如说要测试action层,我总是从action层调用service再调用dao访问数据库,这种方式从原则上来说是无疑是非常正确的,在没用mock框架之前我就隐隐约约的感觉到了这种方式有个不足的地方,那就是速度问题,测试action层的时候需要访问下面两层,如果我们下面两层已经经过单元测试证明是ok的,那么如果测试action层的时候再调用下面两层就等于是做了重复的动作,逻辑上没问题,只是有点重复,并且速度很慢,毕竟项目做到靠后期的时候文单元测试非常多,maven在自动测试的时候速度会非常慢。
而mock框架原理就是模拟对象,方法调用,异常抛出等动作,文档上面介绍他主要解决的问题是项目中有时候依赖不存在的情况下来模拟一来,然而我却是因为速度问题用这个框架,造成这个现象的原因是因为我的项目原因,因为项目不大,逻辑不是很复杂,我在开发的时候往往能从dao、service到action一气呵成来做,不存在模拟依赖的问题,而只是想要解决测试的时候性能问题。当然我的情况是个例,不过我认为mock框架的作用就是这两个:
1.模拟依赖
2.解决单元测试的重复测试来提升性能。
Mockito的使用:我们以User类来测试。
1.把包加入到project中来:此处版本为1.9.5。
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
2.POJO
public class User {
private String id;
private String name;
private Integer age;
// getter,setter
}
3.UserDao,此处的接口是没有实现的,我们就是为了能模拟接口的实现,感觉上就像Spring为此接口注入了实现一样
public interface UserDao {
User insertUser(User user); void deleteUser(User user);
}
4.UserService
public interface UserService {
User insertUser(User user); void deleteUser(User user);
}
5.UserServiceImpl

public class UserServiceImpl implements UserService { private UserDao userDao; public UserServiceImpl() {} public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
} public User insertUser(User user) {
return userDao.insertUser(user);
} public void deleteUser(User user) {
userDao.deleteUser(user);
} }

6.测试
package com.dxz.mockito; import java.util.LinkedList; import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito; public class UserServiceTest { private UserService userService; @Test
public void insertUserTest() {
// pojo对象
User user = new User();
user.setId("123");
user.setName("Jay");
user.setAge(100); // mock一个userDao对象,本来是不存在的
UserDao userDao = Mockito.mock(UserDao.class);
Mockito.when(userDao.insertUser(user)).thenReturn(user);
User u = userDao.insertUser(user);
System.out.println(u); // 这里模拟Spring给userService注入userDao
userService = new UserServiceImpl(userDao);
User us = userService.insertUser(user);
System.out.println(us); // 测试结果ok
Assert.assertEquals(us, user); // 在开发中有接口UserDao但是没有实现,因此UserService里面的userDao属性也是没有实现的,
// 模拟Spring给UserService里面的userDao注入一个实现,实际上没有注入,而仅仅是mock了一个userDao
// 在userService调用insertUser(User user)方法的时候就能模拟实现
// 当然这里仅仅mock了方法调用返回,还有mock异常,验证调用次数等
// 从整个来讲,这个框架是十分简单易用功能强大的,这里的简单是指使用简单,框架本身是相当复杂的
}
}
web编程中,代码一般分3层,controller层,service层,DAO层,分别的测试方法为:
DAO层:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = com.dxz.common.dao.MySqlAutoConfiguration.class)
@EnableAutoConfiguration
@MapperScan("com.dxz.risk.mapper")
//@ActiveProfiles("sonar")
@Ignore
public class RiskBacklistMapperTest { private static final Logger LOG = LoggerFactory.getLogger(RiskBacklistMapperTest.class); @Autowired
RiskBacklistMapper riskBacklistMapper; RiskBacklist riskBacklist; @Before
public void setUp() throws Exception {
riskBacklist = new RiskBacklist();
riskBacklist.setMemberId("123");
riskBacklist.setMsisdn("13530030000");
riskBacklist.setUsername("duanxz");
riskBacklist.setState(1);
riskBacklist.setPlateform(new Byte("1"));
} @Test
public void testInsert() {
riskBacklistMapper.insert(riskBacklist);
}
// 事务自动回滚,默认是true。可以不写
@Test
@Transactional
@Rollback(true)
public void testUpdateByPayId() {
RiskBacklist riskBacklistTemp = riskBacklistMapper.queryByMsisdn("13530030927");
LOG.info("query from db={}", riskBacklist);
if(riskBacklistTemp != null) {
riskBacklistTemp.setUsername("duanxz2");
int result = riskBacklistMapper.updateByPrimaryKey(riskBacklistTemp);
LOG.info("result={}", result);
assertEquals(1, 1);
} else {
LOG.info("result={}", "");
} }
}
service层:
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("sonar")
@Ignore
public class BacklistCheckServiceImplMockTest { private static final Logger LOG = LoggerFactory.getLogger(BacklistCheckServiceImplMockTest.class); /**
* 被注入mock对象的类,即被测试的类
*/
@Autowired
@InjectMocks
private BacklistCheckService backlistCheckService; BacklistReqDTO reqDTO; /**
* 需要mock的DAO
*/
@Mock
private RiskBacklistMapper riskBacklistMapper; @Before
public void setUp() throws Exception {
reqDTO = new BacklistReqDTO();
reqDTO.setMsisdn("13530030000"); RiskBacklist riskBacklist = new RiskBacklist();
riskBacklist.setMsisdn("13530030000");
riskBacklist.setPlateform(1);
riskBacklist.setState(2);
riskBacklist.setUsername("duanxz");
Mockito.when(riskBacklistMapper.queryByMsisdn("13530030000")).thenReturn(riskBacklist);
} @Test
public void isBacklist() {
boolean result = backlistCheckService.isBacklist(reqDTO);
LOG.info("result={}", result); //断言对比业务结果
assertEquals(true, result);
} }
controller层:
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("sonar")
@Ignore
public class BacklistCheckControllerMockTest { /**
* 模拟MVC对象,通过MockMvcBuilders.webAppContextSetup(this.wac).build()初始化。
*/
private MockMvc mockMvc; /**
* 被注入mock对象的类,即被测试的类
*/
@InjectMocks
private BacklistCheckController backlistCheckController; /**
* 需要mock的DAO
*/
@Mock
private BacklistCheckService backlistCheckService; private BacklistReqDTO reqDTO; @Before
public void setUp() throws Exception {
reqDTO = new BacklistReqDTO();
reqDTO.setMsisdn("13530030927");
mockMvc = MockMvcBuilders.standaloneSetup(backlistCheckController).build(); Mockito.when(backlistCheckService.isBacklist(reqDTO)).thenReturn(true);
} @Test
public void testIsBacklist() throws Exception {
MvcResult result = mockMvc
.perform(post("/isBacklist").contentType(MediaType.APPLICATION_JSON).content(GsonUtils.toJson(reqDTO)))
.andExpect(status().isOk())// 模拟向testRest发送get请求
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))// 预期返回值的媒体类型text/plain;charset=UTF-8
.andReturn();// 返回执行请求的结果 // 打印结果,给研发看的
System.out.println(result.getResponse().getContentAsString()); RespResult<Boolean> resultObj = GsonUtils.fromJson2Object(result.getResponse().getContentAsString(),
RespResult.class); //断言对比返回码
assertEquals(RespSystemCode.SUCCESS.getCode(), resultObj.getRespCode());
//断言对比业务结果
assertTrue(resultObj.getData());
} }
框架Mockito的更多相关文章
- mock测试框架Mockito
无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访 ...
- 测试驱动开发神器框架Mockito
作为菜鸟的我,以前没接触过Mock类型的框架,比如说要测试action层,我总是从action层调用service再调用dao访问数据库,这种方式从原则上来说是无疑是非常正确的,在没用mock框架之前 ...
- 测试框架Mockito使用笔记
Mockito,测试框架,语法简单,功能强大! 静态.私有.构造等方法测试需要配合PowerMock,PowerMock有Mockito和EasyMock两个版本,语法相同,本文只介绍Mockito. ...
- Java测试框架Mockito源码分析
1.Mockito简介 测试驱动的开发(Test Driven Design, TDD)要求我们先写单元测试,再写实现代码.在写单元测试的过程中,一个很普遍的问题是,要测试的类会有很多依赖,这些依赖的 ...
- Mock测试框架(Mockito为例)
在做单元测试的时候,有的时候用到的一些类,我们构造起来不是那么容易,比如HttpRequest,或者说某个Service依赖到了某个Dao,想构造service还得先构造dao,这些外部对象构造起来比 ...
- Mockito:一个强大的用于Java开发的模拟测试框架
https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...
- [转载]5分钟了解Mockito
原文链接: http://liuzhijun.iteye.com/blog/1512780/ 5分钟了解Mockito 博客分类: Open SourceJava 一.什么是mock测试,什么是moc ...
- 用Mockito测试SpringMVC+Hibernate
用Mockito测试SpringMVC+Hibernate 译自:Spring 4 MVC+Hibernate 4+MySQL+Maven integration + Testing example ...
- 15类Android通用流行框架
15类Android通用流行框架 Android流行框架 缓存 DiskLruCache Java实现基于LRU的磁盘缓存 图片加载 Android Universal Image Loader 一个 ...
随机推荐
- docker link
什么是docker的link机制 同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,前者会导致ip地址的硬编 ...
- Linux FTP 上传一键脚本
下面来介绍一下这个 FTP 上传一键脚本 ftp_upload.sh. 用途:用于在Linux系统下搭建FTP客户端向FTP服务器端上传文件: 总结一下 ftp_upload.sh 特点:1.支持文件 ...
- 深入Spring:自定义注解加载和使用
前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑.特别是开发Web应用时,我们会频繁的定义@Controller,@Service ...
- GDKOI2017游记
去年的GDKOI在寒假(虽然我没参加),但由于一些机♂缘♂巧♂合♂,比赛时间变成了开学之后的第一周,于是直接导致了当我的同学们在认真学习的同时,我在广州无所事事地和同学谈♂笑♂风♂生♂.(太好了,可以 ...
- Flume架构及运行机制
flume 作为 cloudera 开发的实时日志收集系统,受到了业界的认可与广泛应用.Flume 初始的发行版本目前被统称为 Flume OG(original generation),属于 clo ...
- ASPX一句话爆破工具
#include "stdafx.h" #include <stdio.h> #include <Windows.h> #include <stdli ...
- hdu2243 ac自动机+矩阵快速幂
和上一题有点相似,但是这题是求包含的,并且还要求和 可以求所有情况-不包含的情况,所有情况可用矩阵快速幂求得 还有一点就是如果题目说答案余2^64,直接开unsigned long long就行了,会 ...
- vue router按需加载
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router); //按需加载,当渲染其他页面时才加载其组件,并缓存,减少首 ...
- python--*args和**kwargs可变参数
先来看个例子: #! /usr/bin/env python #coding=utf-8 def foo(*args, **kwargs): print('args=',args) print('kw ...
- Hibernate(1)
一.什么是hibernate 1. hibernate是开源的轻量级框架,应用在javaee三层结构中 dao层框架,使用orm思想对数据库进行crud操作 2 .在dao层里面做对数据库crud操作 ...