一、什么是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. asp.net 5 (mvc 6) 获取网站的物理路径

    public static IApplicationEnvironment GetApplication(this RazorPage page) { var ae = page.Context.Re ...

  2. CCNA 课程 一

    OSI 参考模型: 7应用层 6表示层 5会话层 4传输层   --  TCP / UDP (端口号) 3网络层   --  IP (原IP地址,目标IP地址) 2数据链路层  -- ARPA / e ...

  3. HBase-修改表结构

    HBase修改表结构 package com.hbase.HBaseAdmin; import java.io.IOException; import org.apache.hadoop.conf.C ...

  4. Caused by: org.apache.ibatis.binding.BindingException: Parameter 'parameter' not found.解决

    Caused by: org.apache.ibatis.binding.BindingException: Parameter 'company' not found. Available para ...

  5. spring启动加载类,手动加载bean

    方法一: public final class Assembler implements BeanFactoryPostProcessor { private static ConfigurableL ...

  6. pandas的Series

    pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False) 首先介绍一下基本的: d ...

  7. OpenStack日志搜集分析之ELK

    ELK 安装配置简单,用于管理 OpenStack 日志时需注意两点: Logstash 配置文件的编写 Elasticsearch 日志存储空间的容量规划 另外推荐 ELKstack 中文指南. E ...

  8. nova instance启动中的同步与异步

    instance create:nova/api/servers.create -- self.compute_api.create -- self.compute_task_api.build_in ...

  9. Windods7+Anaconda+Tensorflow安装步骤

    1.下载及安装Anaconda Anaconda是python科学计算的集成.下载Anaconda,下载地址:http://continuum.io/downloads. 由于tensorflow目前 ...

  10. 委托+内置委托方法+多播委托+lambda表达式+事件

    委托概念:如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托: 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字 ...