文档章节

Mockito(三)--完整功能介绍

chace0120
 chace0120
发布于 2014/04/01 10:46
字数 1326
阅读 4605
收藏 3
点赞 1
评论 0

回到官网:http://mockito.org/,打开documentation可以看到原文。

强烈建议不熟悉Mockito的同学先看看我写的Mockito(一)入门篇和(二)实例篇之后再来看这篇文章。

因为只有看了前两篇文章才明白mockito的本质以及该如何使用它。

下面是按原文 翻译+注释 的对Mockito全部功能的介绍。

 

1, 使用mockito验证行为。

//首先要importMockito.

import static org.mockito.Mockito.*;

//mock creation

List mockedList = mock(List.class);

//using mock object

mockedList.add("one");

mockedList.clear();

//验证add方法是否在前面被调用了一次,且参数为“one”。clear方法同样。

verify(mockedList).add("one");

verify(mockedList).clear();

//下面的验证会失败。因为没有调用过add("two")。

verify(mockedList).add("two");

原文中的一句话很重要:Once created, mock will remember all interactions.所以mockito知道前面是否调用过某方法。

 

2, 使方法调用返回期望的值。也被称为stubbing

//You can mock concrete classes, not only interfaces

LinkedList mockedList = mock(LinkedList.class);

//stubbing。当get(0)被调用时,返回"first". 方法get(1)被调用时,抛异常。

when(mockedList.get(0)).thenReturn("first");

when(mockedList.get(1)).thenThrow(new RuntimeException());

//following prints "first"

System.out.println(mockedList.get(0));

//following throws runtime exception

System.out.println(mockedList.get(1));

//following prints "null" because get(999) was not stubbed

System.out.println(mockedList.get(999));

默认情况下,对于所有有返回值且没有stub过的方法,mockito会返回相应的默认值。

对于内置类型会返回默认值,如int会返回0,布尔值返回false。对于其他type会返回null。

这里一个重要概念就是: mock对象会覆盖整个被mock的对象,因此没有stub的方法只能返回默认值。

 

//重复stub两次,则以第二次为准。如下将返回"second":

when(mockedList.get(0)).thenReturn("first");

when(mockedList.get(0)).thenReturn("second");

//如果是下面这种形式,则表示第一次调用时返回“first”,第二次调用时返回“second”。可以写n多个。

when(mockedList.get(0)).thenReturn("first").thenReturn("second");

但是,如果实际调用的次数超过了stub过的次数,则会一直返回最后一次stub的值。

如上例,第三次调用get(0)时,则会返回"second".

 

3, 参数匹配

在上例中如果想实现get(任意整数)时,都返回“element”时,该怎么做呢?很简单。

//stubbing 使用了内置的anyint() matcher.

when(mockedList.get(anyInt())).thenReturn("element");

//因此除了anyint()之外,还有其他很多matcher。这里请参考原文。

//使用了matcher一样可以验证被调用的次数。

verify(mockedList).get(anyInt());

这里有一个限制就是,如果在调用方法时需要传入多个参数,其中一个参数使用了argument matcher,那么所有的参数必须都是matcher。

不可以matcher和实际的参数混着用。

 

这里也可以使用custom argument matcher。因为很多时候输入参数不是build-in 类型,而是我们自己写的一些类,或特殊对象。

这时要使用argument matcher,就必须订制特殊的matcher了。

下例是一个特殊的matcher的实例,这个matcher可以匹配任何file对象。

public class SayHiTest {

 @Test
 public void testSayHi() throws Exception {
     File mock = mock(File.class); //首先mock File类。
     //注意new IsAnyFiles()并不是一个matcher,需要调用argThat(new IsAnyFiles()))才返回一个matcher。

     //下句中stub:当调用renameTo方法时,返回false。该方法参数可以是任意file对象。

     when(mock.renameTo(argThat(new IsAnyFiles()))).thenReturn(false); 
     mock.renameTo(new File("test")); 

     //下句verify renameTo方法被调用了一次,同时输入参数是任意file。
     verify(mock).renameTo(argThat(new IsAnyFiles()));
 }
}
 
class IsAnyFiles extends ArgumentMatcher<File> {
    public boolean matches(Object file) {
        return file.getClass() == File.class;
    }
 }

另外一个参数匹配的例子:

            class IsSOAPMessage extends ArgumentMatcher<SOAPMessage> {

                        public boolean matches(Object soapMessage) {

                                    return (soapMessage instanceof SOAPMessage) || soapMessage==null;

                        }

            }

//上面的macther不仅可以匹配任意的SOAPMessage对象,如果输入参数为空也可以匹配上。

这里说一下我犯过的一个错误。

我在做参数匹配的时候,没有考虑到输入参数为空的情况,导致matcher匹配不上,进而stub的行为无法生效。

其实在发现mock对象没有想自己想象的方式工作时,最好的方法就是debug进去,首先要先确定mock对象是不是真的传递进去了。然后再一步步的debug。

通常遇到的两种情况就是1,mock对象没有传递进去。2,参数没有匹配上。


4, 验证方法被调用了特定次数/至少x次/最多x次/从未被调用

//是否add("twice")被调用了两次。

 verify(mockedList, times(2)).add("twice");

//验证add("twice")被调用了至少一次。以及其他。

verify(mockedList, atLeastOnce()).add("twice");

verify(mockedList, atLeast(2)).add("twice");

verify(mockedList, atMost(5)).add("twice");

verify(mockedList, never()).add("twice");

 

5, 调用方法时抛出异常

doThrow(new RuntimeException()).when(mockedList).clear();

后面还会再介绍几个类似的方法,例如doReturn()。

 

6, 验证顺序

//下面的代码验证firstMock先被调用,secondMock后被调用。

inOrder.verify(firstMock).add("was called first");

inOrder.verify(secondMock).add("was called second");

 

7, 验证mock之间没有相互作用6,7都不是很明白实际意义是什么。


8, 找到冗余的调用

用never()就可以实现,不多说


9, 使用@mock 定义mock。


之前都是使用mock()来模拟一个对象。用@mock是一个shorthand。

public class ArticleManagerTest {

@Mock private ArticleCalculator calculator;

@Mock private ArticleDatabase database;

@Mock private UserProvider userProvider;

private ArticleManager manager;

之后再继续介绍mockito复杂一点的功能。

© 著作权归作者所有

共有 人打赏支持
chace0120
粉丝 35
博文 47
码字总数 41091
作品 0
安阳
程序员
Kotlin 写 Android 单元测试(三),Mockito mocking 框架的使用

Kotlin 写 Android 单元测试系列: Kotlin 写 Android 单元测试(一),单元测试是什么以及为什么需要 Kotlin 写 Android 单元测试(二),JUnit 4 测试框架和 kotlin.test 库的使用 Kotlin...

JohnnyShieh ⋅ 2017/12/14 ⋅ 0

PowerMock介绍

一、为什么要使用Mock工具 在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,远程服务, 文件系统等等)。 而我们没法控制这些外部依赖...

JackieYeah ⋅ 2013/08/26 ⋅ 0

Java工具及框架汇总

如今软件的复杂度已经超过了程序员们理解的极限,我们在每日的编程中不需要从轮子造起,众多成熟稳定的框架可以帮我们简化开发,避免踩坑。 此文记录了我平时工作中常用的一些框架,及其简短...

rathan0 ⋅ 2016/01/15 ⋅ 0

用PowerMock进行Android单元测试与BDD行为驱动开发

很久之前就有听说过mockito和PowerMock的大名了,无奈我司写单元测试的风气不浓,加上一直以来业务繁忙,惰性使我一直没有写单元测试的习惯。 正好现在手头上的是一个全新的项目,可以在初期有时...

嘉伟咯 ⋅ 2017/08/26 ⋅ 0

Mockito(一)——入门篇

Mockito是一种mock工具/框架。我理解EasyMock有点过时了,Mockito是现在比较流行的。 什么是mock?说的直白一点,大家都知道unit test应该是尽可能独立的。对一个class的unit test不应该再和...

chace0120 ⋅ 2014/04/01 ⋅ 0

Mockito 简明教程

原文同步至 Mock 测试是单元测试的重要方法之一。本文介绍了基于 Java 语言的 Mock 测试框架 -- Mockito 的使用。 什么是 Mock 测试 Mock 测试就是在测试过程中,对于某些不容易构造(如 Ht...

waylau ⋅ 2016/02/19 ⋅ 2

Mockito 中文文档 三

27. 委托调用真实实例 (Since 1.9.5) 当使用常规的 spy API 去 mock 或者 spy 一个对象很困难时可以用 delegate 来 spy 或者 mock 对象的某一部分。 从 Mockito 的 1.10.11 版本开始, dele...

张贴在 ⋅ 2016/06/27 ⋅ 0

Mockito 测试介绍

测试工作中,比较耗费时间的工作: 对远程数据库的依赖 调用第三方应用的耗时(主要是网络交互错误、响应时间) 运行较慢的系统(需要等待) 真实对象尚不存在(比如需要用到其他产品的部分模...

AlexPeng ⋅ 2014/04/08 ⋅ 0

JAVA单元测试mock框架

JAVA单元测试mock框架 无标题2016-07-17298 阅读 JAVA 一.概述 最近在做代码重构,发现系统中的UT很少,重构没有UT的话,全部得人工测试,逻辑覆盖不一定全部能覆盖到,因此UT还是很有必要存...

无标题 ⋅ 2016/07/17 ⋅ 0

spring-test单元测试(三)-spring mvc请求测试

上篇文章中我们介绍了如何在struts环境下,进行模拟action的请求测试,以及我们使用了EasyMock框架,来模拟对象的行为。这篇文章我们会继续介绍spring mvc环境下如何对controller进行单元测试...

新栋BOOK ⋅ 2016/11/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

HiSDP —— 高效的C++软件开发平台

目前阿里集团每天有近1000PB的数据是通过LogAgent采集的,为了让LogAgent做到资源占用节省和高效采集,背后是基于HiSDP去构建的。 缘由 当决定采用C++编程语言去开发一个软件时,紧接着所面临...

阿里云云栖社区 ⋅ 20分钟前 ⋅ 0

zookeeper-3.4.12 下载与安装教程

一、zookeeper下载地址 http://mirrors.hust.edu.cn/apache/zookeeper/ 二、启动教程 把压缩包放在指定目录下 第三: 进入 conf文件夹底下 zoo_sample.cfg 文件名改成 zoo.cfg 第四步: 进入b...

泉天下 ⋅ 21分钟前 ⋅ 0

Oracle 中文日期转换

SELECT TO_date('2011年11月11日', 'yy"年"mm"月"dd"日"') FROM DUAL; 1. Oracle无法识别中文格式,所以添加双引号。 2. 后面的格式是指字符串在转换前的格式,而不是指转换后的格式。...

江戸川 ⋅ 22分钟前 ⋅ 0

MySell:API Spring Boot

起步 类目 商品 订单

BeanHo ⋅ 25分钟前 ⋅ 0

Spring方法拦截器MethodInterceptor

参考资料 1、Spring方法拦截器MethodInterceptor 2、Sharding JDBC源码分析-JdbcMethodInvocation类的作用

哎小艾 ⋅ 28分钟前 ⋅ 0

正则表达式

元字符 元字符,又叫字符集,就是用一些特殊符号表示特定种类的字符或位置。 匹配字符 . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配任意的空白符 \d 匹配数字 匹配...

wangchen1999 ⋅ 28分钟前 ⋅ 0

数据库数据导入Elasticsearch案例分享

基于bboss持久层和bboss elasticsearch客户端实现数据库数据导入es案例分享(支持各种数据库和各种es版本) 1.案例对应的源码 https://gitee.com/bboss/bboss-elastic/blob/master/bboss-el...

bboss ⋅ 29分钟前 ⋅ 0

动手---sbt(2)

参考 https://blog.csdn.net/leishangwen/article/details/46225587 建立一个chisel_max目录,文件内容如后面所述,现在开始执行命令: joe@joe-Aspire-Z3730:/media/sdb4/download/scala$ c......

whoisliang ⋅ 36分钟前 ⋅ 0

纯js实现最简单的文件上传(后台使用MultipartFile)

<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>XMLHttpRequest上传文件</title> <script type="text/javascript"> //图片上传 var xhr......

孟飞阳 ⋅ 41分钟前 ⋅ 0

iOS宇宙大战游戏、调试工具、各种动画、AR相册、相机图片编辑等源码

iOS精选源码 日期时间选择器,swift Space Battle 宇宙大战 SpriteKit游戏源码 LLDebugTool - 便捷的IOS调试工具(新增截屏功能) 相机扫描or长按识别二维码、FMDB、键盘动态高度、定位等 动画...

sunnyaigd ⋅ 41分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部