一、什么是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. IntelliJ IDEA 中 右键新建时,选项没有Java class的解决方法和具体解释

    我是在别人问我的时候,才发现还可以有这个问题,主要是他新项目直接打开,什么都没配置,就打算新建文件,其实可以直接看编辑器右下角的event log,那个对话框点开的话,可以add as maven p ...

  2. MyBatis联合查询association使用

    1.需求 两张表 channels(频道表)  member(会员表) 频道表里面有会员id,查询频道列表的时候需要关联查询出会员的名称,头像等信息 . 2.channels.xml定义,配置主要在这 ...

  3. sqlserver ,镜像数据库,CDC,实时监控数据变化

    1.数据库镜像配置 1)主机环境:计算机名称修改SQL1.xiaoping.com 添加用户sqluser 密码永不变,率属于administrators sqlserver安装时,将所有sqlser ...

  4. HBase-建表(普通建表及预分区建表)

    package com.hbase.HBaseAdmin; import java.io.IOException; import org.apache.hadoop.conf.Configuratio ...

  5. Apache Phoenix基本操作-1

    本篇我们将介绍phoenix的一些基本操作. 1. 如何使用Phoenix输出Hello World? 1.1 使用sqlline终端命令 sqlline.py SZB-L0023780:2181:/ ...

  6. 【转】Vue.js:轻量高效的前端组件化方案

    摘要:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统.在前端纷繁复杂的生态中,Vue.js有幸受到一定程度的关注,目前在GitHub上已经有5000+的star.本文将从各方面对Vue ...

  7. javascript的宿主环境

    关于javascript语言,最有意思的是它必须要在一个宿主环境中运行,其中受欢迎的宿主环境当然就是浏览器了,但这并不是我们唯一的选择, javascript完全可以运行在服务器端,桌面以及富媒体环境 ...

  8. 微信小程序申请。很蛋疼的流程。

    微信小程序申请. 营业执照,食品许可证,身份证正面,身份证反面. 1.先要申请服务号. 需要一个QQ邮箱,申请服务号. 填写各种信息,营业执照信息. 法人信息. 管理员用自己人的.方便开发操作. 申请 ...

  9. Android dependency has different version.You should manually set the same version via DependencyReso

    有时候导入一些module时,会出现以下问题 Android dependency 'com.android.support:support-v4' has different version for ...

  10. 设置浏览器地址栏URL前面显示的图标

    其实很简单,你只做个ico图标,命名为favicon.ico,把它传到你的页面下面. 并在相应的页面里加上代码  在页面<heah></heah>之间加, <link r ...