Mockito简单实用教程 - 第一部分mock

  • 环境介绍
  • 依赖
  • 内容
    • 1. 检验方法是否有被调用
    • 2. 指定mock方法的返回值
    • 3. 验证指定次数
    • 4. 验证异常
    • 5. 校验执行顺序
    • 6. 校验形参
    • 7. 参数匹配
  • 参考

环境介绍

  • Junit 4

依赖

分别引入Junit4和Mockito的依赖

<dependencies><dependency><groupId>org.mockito</groupId><artifactId>mockito-all</artifactId><version>1.9.5</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>

引入完依赖后,就可以开始我们的Mockito的使用了。

内容

1. 检验方法是否有被调用

 @Testpublic void should_call_add_and_clear_method() {// 我们可以mock 一个List接口List mockedList = mock(List.class);mockedList.add(1);mockedList.clear();verify(mockedList, times(1)).add(1);// 因为verify方法默认times为1,还可以写为下面这种形式verify(mockedList).clear();}

2. 指定mock方法的返回值

 @Testpublic void should_return_10_when_get_0() {List mockList = mock(List.class);when(mockList.get(0)).thenReturn(10);assertEquals(10, mockList.get(0));//针对于一下没有mock返回值的方法,都会返回默认值(基本类型返回0或者false,引用类型则为null)assertNull(mockList.get(999));}

3. 验证指定次数

 @Testpublic void indicate_explicit_verify_count() {List mockList = mock(List.class);mockList.add("once");mockList.add("twice");mockList.add("twice");mockList.add("three times");mockList.add("three times");mockList.add("three times");verify(mockList).add("once");verify(mockList,times(2)).add("twice");verify(mockList,times(3)).add("three times");verify(mockList,times(0)).add("never added");}

4. 验证异常

验证异常有三种方法:

  • @Test(expected=XXX) (Mockito可以只看这种方式)
  • 使用try…catch…fail()
  • 使用JUnit的@Rule注解
  1. @Test(expected=XXX)
 @Test(expected = RuntimeException.class)public void should_throw_RuntimeException1() {List mockList = mock(List.class);//mock当调用add()方法并且参数是1时,抛出RuntimeExceptionwhen(mockList.add(1)).thenThrow(new RuntimeException());//下面的mock抛出异常的方式,其实是上面这一个方法的变种,具体差别不大//doThrow(new RuntimeException()).when(mockList).add(1);mockList.add(1);}
  1. 使用try…catch…fail()
 @Testpublic void should_throw_RuntimeException_use_try_catch_fail() {List mockList = mock(List.class);when(mockList.add(1)).thenThrow(new RuntimeException());try {mockList.add(1);// 如果没有跑异常,则执行到fail方法时,该测试就不通过了fail();}catch (RuntimeException e){// 如果具体方法实现中有catch住异常,还有打logger的话就可以verify logger使用有被调用// 或者继续assert其他的结果}}
  1. 使用JUnit的@Rule注解
    如果要使用这种方式进行校验时,需要加多一个依赖,并且需要放在JUnit依赖的前面
 @Rulepublic ExpectedException expectedException = ExpectedException.none();@Testpublic void should_throw_RuntimeException_use_rule() {List mockList = mock(List.class);when(mockList.get(1)).thenThrow(new RuntimeException("this is runtime exception"));expectedException.expect(RuntimeException.class);// 下面是检验异常信息(非必要)expectedException.expectMessage("runtime exception");mockList.get(1);}

三种校验异常的校验方式的区别:

  • @Test(expected=xxx)。只能校验抛出的异常,但是无法再继续校验 抛出异常地方后面的内容了。
  • try…catch…fail。fail也是Junit的方法,对比第一种的校验方式,出现异常后,还能在被catch后继续校验后面的内容
  • 使用JUnit的@Rule注解,跟第一种相同,但是它还能校验异常的信息,支持正则匹配和SubString.

总的来说,第一二种就够用了,第三种稍微是麻烦了点。

5. 校验执行顺序

 @Testpublic void verify_method_called_in_order() {List mockList = mock(List.class);mockList.add("first");mockList.add("second");mockList.add("third");mockList.add("fourth");//此处可以加入多个对象到InOrder中,必须按照调用的顺序去verifyInOrder inOrder = inOrder(mockList);// 如果调换了一下顺序,测试就跑不过了inOrder.verify(mockList).add("first");  // 1inOrder.verify(mockList).add("second"); // 2inOrder.verify(mockList).add("third");  // 3inOrder.verify(mockList).add("fourth"); // 4}

6. 校验形参

 @Testpublic void test_capturing_arguments() {ArgumentCaptor<Integer> ageCaptor = ArgumentCaptor.forClass(Integer.class);// 关于spy在下一部分再说,这里可以当成简单去new了一个实例Person person = spy(new Person());person.increaseAge(100);person.increaseAge(1000);// 在verify中校验调用次数,并且使用capture方法捕获形参verify(person,times(2)).setAge(ageCaptor.capture());// 获取调用set方法时所有的形参// 我们调用了两次increaseAge,所以也会调用两次setAge, params:{100,1000}List<Integer> params = ageCaptor.getAllValues();assertEquals(2, params.size());assertEquals(Integer.valueOf(100), params.get(0));assertEquals(Integer.valueOf(1000), params.get(1));}class Person{private int age;public void setAge(int age){this.age = age;}public void increaseAge(int increment){setAge(increment);}}

除了上面的方式,我们还可以通过注解的方式去实现捕获参数

// 第一种,直接在测试类上加
@Runwith(MockitoJUnitRunner.class)
public class TestMockitoOneTest {//    第二种,在@Before的方法中加入
//    @Before
//    public void setUp() throws Exception {//        MockitoAnnotations.initMocks(this);
//    }//    第三种,放在构造方法中
//    public TestMockitoOneTest() {//        MockitoAnnotations.initMocks(this);
//    }@CaptorArgumentCaptor<Integer> argumentCaptor;@Testpublic void test_capturing_arguments_by_annotation() {Person person = spy(new Person());person.increaseAge(100);person.increaseAge(1000);verify(person,times(2)).setAge(argumentCaptor.capture());List<Integer> params = argumentCaptor.getAllValues();assertEquals(2, params.size());assertEquals(Integer.valueOf(100), params.get(0));assertEquals(Integer.valueOf(1000), params.get(1));// getValue则是保存最后一次捕获时,参数的值assertEquals(Integer.valueOf(1000), argumentCaptor.getValue());}
}

如果要使用Mockito的注解的话,我们必须还需要额外多加一点内容,让注释能够正常生效,不然测试会直接报NPE
方法有三种:

  • 直接在测试类上加上@Runwith(MockitoJUnitRunner.class)
  • 在加了@Before注解的方法中加上 MockitoAnnotations.initMocks(this)
  • 可以在测试类的构造方法中加上 MockitoAnnotations.initMocks(this).
    但是第三种方法目前仅限于JUnit 4,因为JUnit 4 为了让各个测试方法不相互影响,执行每个测试方法时,会重新实例化测试类对象。

7. 参数匹配

 @Testpublic void test_argument_matcher_by_Anonymous_class() {// 类似java里面可以自定义比较器一样,Mockito也可以自定义参数的比较器// 如果有需要mock 对比集合里面的元素时,我们就可以去自定义比较器List mockList = mock(List.class);// 参数一般填需要比较的对象的类型即可when(mockList.contains(argThat(new ArgumentMatcher<Integer>() {public boolean matches(Object o) {return (Integer)o == 1;}}))).thenReturn(true);assertTrue(mockList.contains(1));}@Testpublic void test_argument_matcher_by_inner_class() {List mockList = mock(List.class);when(mockList.contains(argThat(new OddMatcher()))).thenReturn(true);assertFalse(mockList.contains(1));assertTrue(mockList.contains(2));assertFalse(mockList.contains(3));assertTrue(mockList.contains(4));}class OddMatcher extends  ArgumentMatcher<Integer>{public boolean matches(Object o) {return ((Integer)o & 1) == 0;}}

参考

官网

Mockito简单实用教程 - 第一部分mock相关推荐

  1. 【ffmpeg】最全简单实用教程|安装音频视频剪切融合拼接抽帧等

    ffmpeg 实用教程(非常全) FFmpeg Download(Mac) brew ffmpeg 常用操作(最全最简单) 音频 音频转换格式 多个音频混音 改变音量大小 音频淡入淡出 调整音频速率 ...

  2. knockout.js简单实用教程1

    第一次接触knockout是在一年多之前吧.当时是接手了一个别人的项目,在项目中有用到knockout来进行数据的绑定.也就开始学习起来knockout.在之后的项目中也多次用到了这个.在第一次开始学 ...

  3. 【超简单实用教程】mkv、flv格式转mp4格式(附网盘资源)

    原写在自己的B站专栏,为了方便,把那篇删了,只放在CSDN里了. 之前看到有人推荐过类似的技术入门帖,想到了自己当初也是从什么都不明白一点点摸索的.不过这篇文章只提了mkv的格式转换,我想顺着这个思路 ...

  4. 安装Windows、Ubuntu双系统超简单实用教程

    目录 一.版本选择 二.安装步骤 1.查看电脑配置 2.制作系统盘 3.在windows下创建空白分区 4.安装系统 Hey, guys!相信很多小伙伴在安装Windows.Ubuntu双系统过程中遇 ...

  5. 网站制作---科讯万能搜索系统的简单实用教程

    很多科汛fans已对系统自带的的简单搜索感谢不满足了,比如做人才网的用户希望能根据职位类型,工作地点,关键字等进行精确搜索,这时如果用KesionCMS自带搜索标签显然不符合要求.很幸运KesionC ...

  6. 库卡kuka仿真软件sim Pro 3.1简单实用教程

    实验目的 建立机器人,自定义抓手,导入外部模型,掌握工具坐标.基坐标的使用,自动生成轨迹. 实验步骤 打开KUKA.Sim Pro 3.1.2仿真软件,依次点击KUKA Sim Library 3.1 ...

  7. 华硕电脑怎么录屏?华硕电脑录屏功能在哪?简单实用教程来了

    ​有很多小伙伴对如何录制华硕电脑的屏幕知识和信息知之甚少.现在大家都想多了解一些关于华硕电脑怎么录屏的相关知识和信息.所以今天小编收集了一些关于如何录制华硕电脑屏幕的知识和信息,与大家分享. 华硕电脑 ...

  8. EVE安装与简单使用教程

    一.简单安装教程 第一步:eve软件下载(汉化.英文) 参考网址:http://eve-ng.cn/doku.php,里面很全,根据自己需求进行下载,我下载的汉化版 第二步:用VMware虚拟机打开下 ...

  9. matlab简单程序实例_visual basic VB.NET实例系列教程第一节(简单实用抽奖程序)...

    近期疫情原因,工作比较不忙,所以打算出一套零基础,VB.NET实例系列入门教程,实用又好玩,带大家进入VB的编程世界里,希望这套图文教程能帮到有需要的人! 第一节(简单实用抽奖程序) 内容准备:编译环 ...

最新文章

  1. Ubuntu~Tensorflow~GPU
  2. 使用帆软finereport实现跳转的一点心得
  3. 【PAT乙级】1065 单身狗 (25 分)
  4. vue教程4:自定义组件的使用
  5. 再谈全局网HBase八大应用场景
  6. SQL笔记-Oracle中varchar和varchar2的区别
  7. 软件工程 speedsnail 第二次冲刺1次
  8. c语言正则表达式库,c语言正则表达式库--PCRE
  9. 文件操作命令(TYPE)
  10. 如何在excel表格中查找重复值
  11. 连接mysql失败怎么办_数据库连接失败有什么原因?怎么解决?
  12. 域用户本地管理员密码破解
  13. 对于神经网络学习 Maxwell 方程的思考——泛化能力
  14. 浏览器指纹:原来我们一直被互联网巨头监视,隐私在网上裸奔、无处可藏
  15. sqlserver-创建表
  16. 超级炫酷的动态登陆界面视频背景
  17. 接口测试平台代码实现2:本平台项目目录解析
  18. 自动复制吱口令html,【月入六万】吱口令,网页自动复制,进支付宝提示领红包源码...
  19. 用快解析内网穿透实现零成本自建网站
  20. 技术2---swagger2

热门文章

  1. 通过以太坊实现自己的ICO
  2. 学习人工智能必读这30本书!
  3. mysql: [Warning] Using a password on the command line interface can be insecure.解决方法
  4. 【blender建模功能】06 多边形建形工具
  5. CLion配置STM32开发环境(JLink GDB Server)
  6. 163VIP邮箱如何注册?163VIP企业邮箱申请介绍!
  7. NASA全球生态系统动态调查激光雷达(GEDI)
  8. 机器学习的一些感悟(一)
  9. html和css学习课件(新版)
  10. commons-io工具包的基本使用