1.验证一些属性

因为大部分人都很熟悉这些接口(例如add(),get(),clear()等方法),下面是一个mock个List的例子。

在实际情况下,请直接使用List真实实例,而不要去mock。

 //Let's import Mockito statically so that the code looks clearer// 引入包import static org.mockito.Mockito.*;//mock creation// mock实例List mockedList = mock(List.class);//using mock object// 像List真实实例一样,使用mock对象mockedList.add("one");mockedList.clear();//verification// 作些验证verify(mockedList).add("one");verify(mockedList).clear();

当一个mock实例被创建后,它会记录所有交互行为。然后,你可以根据需要进行验证。

2.如何进行打桩(How about some stubbing?)

 //You can mock concrete classes, not just interfaces// 不仅是接口,也可以mock具体类LinkedList mockedList = mock(LinkedList.class);//stubbing// 桩函数when(mockedList.get(0)).thenReturn("first");when(mockedList.get(1)).thenThrow(new RuntimeException());//following prints "first"// 下面代码将会打印"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// 下面语句,由于没有进行打桩,就会得到nullSystem.out.println(mockedList.get(999));//Although it is possible to verify a stubbed invocation, usually it's just redundant// 尽管可以验证一个桩函数的调用,但这通常都是多余的//If your code cares what get(0) returns, then something else breaks (often even before verify() gets executed).// 如果你的代码关心get(0)的返回,然后,一些事情会被打破(这通常是在verify()函数被调用前)//If your code doesn't care what get(0) returns, then it should not be stubbed. Not convinced? See here.// 如果你的代码不关心get(0)的返回,便不需要打桩了。不服,那就看这里verify(mockedList).get(0);

默认情况下,所有有返回值的方法,一个mock对象都会返回一个适当值,比如null,或者内置类型或内置类型的装箱值,或者一个空的集合。例如,0作为返回值为int/Integer的返回,false,作为返回值为boolean/Boolean的返回;

桩函数可以被重写:例如,公共桩函数可以用来安装测试夹具(fixture setup),但测试方法可以重写它。请记住重新装函数,通常是表示有潜在代码被打桩太多的味道;

一旦被打桩(stubbed),则方法会总是返回桩值,无论方法被调用多少次。上面的原则很重要——当你对一些方法多次用同一个值进行打桩时。换句话说:打桩的顺序是有关系的(the order of stubbing matters),一般情况下意义不大,只有在桩(stubbing)恰好是同样方法的调用或者使用参数参数匹配器(argument matchers)时。

3.参数匹配器 (Argument matchers)

Mockito通常用Java语法方式的equals()函数来验证参数值。有些时候,当你需要额外的灵活性时,你也可以用参数匹配器

//stubbing using built-in anyInt() argument matcher
// 使用内置的anyInt()参数匹配器来打桩when(mockedList.get(anyInt())).thenReturn("element");//stubbing using custom matcher (let's say isValid() returns your own matcher implementation):// 使用自定义参数匹配器(让我们把这个返回自定义匹配的实现叫做isValid())when(mockedList.contains(argThat(isValid()))).thenReturn("element");//following prints "element"// 下面会打印elementSystem.out.println(mockedList.get(999));//you can also verify using an argument matcher// 我们也可以验证参数匹配器verify(mockedList).get(anyInt());//argument matchers can also be written as Java 8 Lambdas// 参数匹配器也可以使用Java 8 的Lambdas表达式来定义verify(mockedList).add(someString -> someString.length() > 5);

参数匹配器增加了验证和打桩的灵活性,点击这里或这里可以查看更多内置匹配器和自定义参数匹配器

关于自定义匹配器的信息,可以参考ArgumentMatcher类的javadoc

要合理使用复杂的参数匹配器。通常情况下,匹配都是使用equals()或偶然使用anyX()来实现一个清晰和简洁的测试。有时候重构代码从而使用equals()匹配或者重写equals()方法,都是比使用复杂参数匹配器更好的方式。

更多信息可以阅读15节或者ArgumentCaptor类的javadoc。ArgumentCaptor是一个特殊的参数匹配器实现,可以为后续断言捕获参数值

注意事项:
如果你使用参数匹配器,则所有的参数,都必须是通过匹配器提供
下面是使用匹配器进行验证的例子,打桩也是同样:

   verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));//above is correct - eq() is also an argument matcher// 上面代码是正确的,eq也是一个匹配器verify(mock).someMethod(anyInt(), anyString(), "third argument");//above is incorrect - exception will be thrown because third argument is given without an argument matcher.// 上面的代码是有问题的,因为第三个参数不是匹配器,所以,会抛出异常

像anyObject(),eq()这样的匹配器方法并不会返回匹配器。在这些方法内部,会在栈上记录一个匹配,然后返回一个傀儡值(通常是null)。这些实现是因为Java编译器的静态类型安全。这种实现的后果就是,你不能在verified/stubbed方法以外的地方使用anyObject(), eq()这些方法。

4. 验证确切次数调用/至少X次/或者没有调用(Verifying exact number of invocations/at least x/never)

 //using mockmockedList.add("once");mockedList.add("twice");mockedList.add("twice");mockedList.add("three times");mockedList.add("three times");mockedList.add("three times");//following two verifications work exactly the same - times(1) is used by default// 下面的两个验证,验证次数——默认是times(1)表示一次verify(mockedList).add("once");verify(mockedList, times(1)).add("once");//exact number of invocations verification// 验证指定次数verify(mockedList, times(2)).add("twice");verify(mockedList, times(3)).add("three times");//verification using never(). never() is an alias to times(0)// 验证重没有调用,never()是times(0)的一个别名verify(mockedList, never()).add("never happened");//verification using atLeast()/atMost()// 至少/最多调用次数的验证verify(mockedList, atLeastOnce()).add("three times");verify(mockedList, atLeast(2)).add("five times");verify(mockedList, atMost(5)).add("three times");

time(1)是默认值,因此,time(1)是可以省略的。

5.通过异常对void方法打桩(Stubbing void methods with exceptions)

doThrow(new RuntimeException()).when(mockedList).clear();//following throws
// 下面的调用会抛出异常
RuntimeException:mockedList.clear();

有关doThrow或doAnswer函数族的更多信息,可以参考12节

验证次序

// A. Single mock whose methods must be invoked in a particular order
// 方式A:一个方法被按照指定次序调用的简单mockList singleMock = mock(List.class);//using a single mock// 使用上面的mocksingleMock.add("was added first");singleMock.add("was added second");//create an inOrder verifier for a single mock// 为single mock创建一个InOrderInOrder inOrder = inOrder(singleMock);//following will make sure that add is first called with "was added first, then with "was added second"// 下面的代码会验证add函数第一次调用参数为"was added first",然后参数是"was added second"inOrder.verify(singleMock).add("was added first");inOrder.verify(singleMock).add("was added second");// B. Multiple mocks that must be used in a particular order// 方式B:多个mock对象的按次序使用List firstMock = mock(List.class);List secondMock = mock(List.class);//using mocksfirstMock.add("was called first");secondMock.add("was called second");//create inOrder object passing any mocks that need to be verified in order// 使用多个mock对象的调用次序创建一个InOrderInOrder inOrder = inOrder(firstMock, secondMock);//following will make sure that firstMock was called before secondMock// 下面的代码验证firstMock对象的add调用是先于secondMock对象inOrder.verify(firstMock).add("was called first");inOrder.verify(secondMock).add("was called second");// Oh, and A + B can be mixed together at will// 当然,A和B方式是可以混合在一起使用的

验证次序是灵活的,你不用把每个方法的调用都验证一遍,你只需要验证那些你真正需要的。还有,你也可以仅仅使用那些需要验证次序的mock对象来创建InOrder对象。

7. 确保mock无交互行为发生(Making sure interaction(s) never happened on mock)

 //using mocks - only mockOne is interacted// mockOne.add("one");//ordinary verification// 普通验证verify(mockOne).add("one");//verify that method was never called on a mock// 验证一个mock的方法永远没有调用verify(mockOne, never()).add("two");// verify that other mocks were not interacted// 确保其他mock对象没有交互行为发生verifyZeroInteractions(mockTwo, mockThree);

8. 检测冗余调用(Finding redundant invocations)

//using mocksmockedList.add("one");mockedList.add("two");verify(mockedList).add("one");//following verification will fail// 下面的验证会失败verifyNoMoreInteractions(mockedList);

警告:
经常使用古典方式,预期-运行-验证,的人倾向于频繁使用verifyNoMoreInteractions(),甚至在每个测试方法里都使用。但verifyNoMoreInteractions()并不被推荐在每个方法里都使用。verifyNoMoreInteractions()是互动测试工具包里一个便利的断言。仅仅在你需要验证冗余调用的时候使用。滥用verifyNoMoreInteractions()会使测试代码很难维护。
never()是一种更加显示和意图明确的方式。

以上内容翻译自Mockito官方教程的1-8节

Mockito教程一相关推荐

  1. AUTOCAD自学教程一

    AUTOCAD自学教程一 AUTOCAD自学教程 在学习任何一款软件的时候,第一步也是非常必要的一步就是如何的安装软件. 下面我们讲解如何的安装这个软件. 1.安装autocad 2.安装产品 3.正 ...

  2. pytorch打印模型参数_Pytorch网络压缩系列教程一:Prune你的模型

    Pytorch网络压缩系列教程一:Prune你的模型 本文由林大佬原创,转载请注明出处,来自腾讯.阿里等一线AI算法工程师组成的QQ交流群欢迎你的加入: 1037662480 深度学习模型取得了前所未 ...

  3. MongoDB 教程一: 安装和使用 (Mongodb启动命令mongod参数说明)

    视频: MongoDB 教程一: 安装和使用 Mongodb启动命令mongod参数说明 我们可以通过mongod --help查看mongod的所有参数说明,以下是各参数的中文解释. 基本配置 –q ...

  4. 初识c语言教程,第1课C语言教程一: 初识C程序.doc

    第1课C语言教程一: 初识C程序 第1课 初识C程序 教学目标 1.计算机语言介绍 2.了解C语言 3.如何学好C语言(多做题,多上机调试程序) 4.C语言上机调试环境 教学过程 计算机程序设计语言的 ...

  5. 大学英语综合教程一 Unit 8 课文内容英译中 中英翻译

    大学英语综合教程一 Unit 8 课文内容英译中 中英翻译   大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客 本文 ...

  6. 大学英语综合教程一 Unit 2 课文内容英译中 中英翻译

    大学英语综合教程一 Unit 2 课文内容英译中 中英翻译   大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客 本文 ...

  7. 原创 | k8s系列教程一:开篇

    作者:潘吉祥 欢迎加入k8s学习系列教程,在接下来的系列文章,你将可以在较短的时间内达到入门k8s的效果. k8s是什么 Kubernetes(K8S)作为Google在2014年发布的一个开源项目, ...

  8. 大学英语综合教程一 Unit 6 课文内容英译中 中英翻译

    大学英语综合教程一 Unit 6 课文内容英译中 中英翻译   大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客 本文 ...

  9. R语言七天入门教程一:配置运行环境

    R语言七天入门教程一:配置运行环境 一.R语言介绍 1.R语言是什么? 参考:R语言教程-R语言介绍 R 语言是为数学研究工作者设计的一种数学编程语言,主要用于统计分析.绘图.数据挖掘.R语言有丰富的 ...

最新文章

  1. 联想服务器x3650硬盘黄灯,服务器故障处理 X3650M4主板故障 硬盘黄灯 内存错误 联想(IBM)服务器配件...
  2. Jquery 选择器大全 【转载】
  3. 优化UGC流程,获得图文并茂游记so easy
  4. python 中 feedparser的简单用法
  5. 谁动了我的工作效率?大咖分享融合通信背后的技术案例
  6. ado.net封装类
  7. Hadoop如何迎击大数据分析的挑战
  8. 如何使用内联onclick属性停止事件传播?
  9. 【ffmpeg】overlay带有透明通道的视频
  10. EdrawMax v12.0.2跨平台图表软件
  11. 推荐一个springboot和springcloud系列的博客专家--方志朋
  12. Microsoft Visio 2003下载
  13. 计算机考研用python_计算机考研408 130+个人攻略
  14. 独家汉化SDL Passolo 2018(软件汉化工具) v18.0.130简体中文版
  15. java获取本地真实ip
  16. (自我归纳)费曼学习法
  17. 如何打造数字原生企业?易捷行云EasyStack有话要说
  18. graylog3.0收集飞塔防火墙日志
  19. 网页播放器实现全屏的方法总结
  20. 雷石 扩展文件服务器,雷石发布KTV软硬件新品:智能手表可点歌

热门文章

  1. 地推外人看来好像是很简单的一件事
  2. LeetCode101——对称二叉树——c++版本实现
  3. 计算机系统多媒体扩展指令集,计算机系统结构.ppt
  4. RV1126 在Ubuntu18.04开发环境搭建与SDK编译
  5. Python:如何查看一个对象有哪些属性、方法以及查询源码中只有pass的方法的参数
  6. ideavim 使用分享
  7. 数学物理方法 07 行波法
  8. 计算机网络-应用层协议5(P2P)
  9. linux配置dns测试外网
  10. 正则验证 手机账号和密码正则验证方法