一、什么是mock测试,什么是mock对象?

先来看看下面这个示例:

从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。

一种替代方案就是使用mocks

从图中可以清晰的看出

mock对象就是在调试期间用来作为真实对象的替代品。

mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。

二、什么是Mockito

Mockito是一个针对Java的mocking框架。它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。

官方网站:http://code.google.com/p/mockito/

在任何应用Mockito的地方,加上如下片段:
pom.xml增加

        <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、验证方法调用次数

 还可以通过atLeast(int i)和atMost(int i)来替代time(int i)来验证被调用的次数最小值和最大值。
 

示例二(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的更多相关文章

  1. mock测试框架Mockito

    无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访 ...

  2. 测试驱动开发神器框架Mockito

    作为菜鸟的我,以前没接触过Mock类型的框架,比如说要测试action层,我总是从action层调用service再调用dao访问数据库,这种方式从原则上来说是无疑是非常正确的,在没用mock框架之前 ...

  3. 测试框架Mockito使用笔记

    Mockito,测试框架,语法简单,功能强大! 静态.私有.构造等方法测试需要配合PowerMock,PowerMock有Mockito和EasyMock两个版本,语法相同,本文只介绍Mockito. ...

  4. Java测试框架Mockito源码分析

    1.Mockito简介 测试驱动的开发(Test Driven Design, TDD)要求我们先写单元测试,再写实现代码.在写单元测试的过程中,一个很普遍的问题是,要测试的类会有很多依赖,这些依赖的 ...

  5. Mock测试框架(Mockito为例)

    在做单元测试的时候,有的时候用到的一些类,我们构造起来不是那么容易,比如HttpRequest,或者说某个Service依赖到了某个Dao,想构造service还得先构造dao,这些外部对象构造起来比 ...

  6. Mockito:一个强大的用于Java开发的模拟测试框架

    https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...

  7. [转载]5分钟了解Mockito

    原文链接: http://liuzhijun.iteye.com/blog/1512780/ 5分钟了解Mockito 博客分类: Open SourceJava 一.什么是mock测试,什么是moc ...

  8. 用Mockito测试SpringMVC+Hibernate

    用Mockito测试SpringMVC+Hibernate 译自:Spring 4 MVC+Hibernate 4+MySQL+Maven integration + Testing example ...

  9. 15类Android通用流行框架

    15类Android通用流行框架 Android流行框架 缓存 DiskLruCache Java实现基于LRU的磁盘缓存 图片加载 Android Universal Image Loader 一个 ...

随机推荐

  1. 在Linux系统下使用Docker以及Weave搭建Nginx反向代理

    Hi, 今天我们将会学习如何使用 Weave 和 Docker 搭建 Nginx 的反向代理/负载均衡服务器.Weave 可以创建一个虚拟网络将 Docker 容器彼此连接在一起,支持跨主机部署及自动 ...

  2. MongoDB快速入门(一)

    MongoDB是一个跨平台,面向文档的数据库,提供高性能,高可用性和易于扩展.MongoDB是工作在集合和文档上一种概念. 数据数 数据库是一个集合的物理容器.每个数据库获取其自己设定在文件系统上的文 ...

  3. C++逗号表达式

    c++中,逗号表达式的结果是最右边表达式的值

  4. iptable防火墙面试题

    第1章 (一)基础口试题 1.1 详述 iptales 工作流程以及规则过滤顺序? 1.防火墙是一层层过滤的.实际是按照配置规则的顺序从上到下,从前到后进行过滤的. 2.如果匹配上了规则,即明确表明是 ...

  5. 互联网高并发之Hystrix实现服务隔离和降级

    当大多数人在使用Tomcat时,多个HTTP服务会共享一个线程池,假设其中一个HTTP服务访问的数据库响应非常慢,这将造成服务响应时间延迟增加,大多数线程阻塞等待数据响应返回,导致整个Tomcat线程 ...

  6. json数据与Gson工具类的使用

    JS中使用JSON JSON对象 --> JSON字符串:JSON.stringify(对象) JSON字符串 --> JSON对象:JSON.parse(JSON字符串) <scr ...

  7. SolrCloud 5.5.5 + Zookeeper + HDFS使用

    安装sol r 三个节点192.168.1.231,192.168.1.234,192.168.1.235 下载安装包solr.tar.gz 解压 tar -zxvf solr.tar.gz 配置ZK ...

  8. HDU 4348 To the moon (主席树区间更新)

    题意:首先给你n个数,开始时间为0,最后按照操作输出 给你四种操作: 1. C l r d :  在(l,r)区间都加上d,时间加一2. Q l r :  询问现在(l,r)的区间和3. H l r ...

  9. POJ 3167 Cow Patterns (KMP+前缀和)

    题意:给你两串数字,长度分别为n和m,数字大小在[1,25].当后一串数字每个数字的排名位置与前一串数字(任一长度为m的子串)每个数字的排名位置一致时就完全匹配,最后求哪些位置是完全匹配的. 例如:1 ...

  10. java调用dll或so动态库文件(c++/c)

    java调用dll或so动态库文件(c++/c) 博客分类:  工作 CC#C++JavaEclipse  java调用dll或so动态库文件(c++/c)开发平台:Eclipse3.3.1.1+CD ...