11

Mockito 一个优秀的 Mock 测试框架

 4 years ago
source link: http://www.justdojava.com/2021/06/05/mockito/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Hello 大家好,我是阿粉,日常工作中很多时候我们都需要同事间的相互配合协作完成某些功能,所以我们经常会遇到服务或者应用内不同模块之间要互相依赖的场景。比如下面的场景,serviceA 中的 methodA() 方式依赖 serviceB 中的 methodB() 方法返回操作的结果。那如果我们要对自己的methodA() 方法进行编写单元测试,还需要等其他同事的methodB() 方法开发完成才行。那有没有什么办法我们可以跳过或者说模拟方法 B 的输出呢?这就引出了我们今天的主角 Mockito,一个优秀的 Mock 测试框架。

1.png

我们通过使用 Mock 技术可以让开发不停滞,Mock技术的作用是将服务于服务之间的依赖在测试自测阶段隔离开,让开发人员在自己的应用内部通过模拟的方式把需要依赖外部的接口给构造出来,从而保证不被外界的开发进度所影响。今天我们要谈到的Mockito 就是一个优秀的 Mock 框架。

Mockito

Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.

Mockito 是一个很好用的模拟框架。它让您可以使用干净简单的 API 编写漂亮的测试。 Mockito 的可读性非常好,不会让你感动迷惑,产生的验证错误也很明确。

官网地址:https://site.mockito.org/

中文文档:https://github.com/hehonghui/mockito-doc-zh#0

测试用例 1

首先在工程的 pom 文件里面加依赖,我们加上 mockito junit 的依赖。

<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.11</version>
  <scope>test</scope>
</dependency>

接下来我们编写一个简单的测试用例,这里我们通过mock 一个 List 对象,先添加几个元素,后面验证添加交互是否与我们预期的一致。

@Test
public void testVerify() throws Exception {
  //创建 mock 对象
  List mockedList = mock(List.class);
  mockedList.add("test1");
  mockedList.add("test2");
  mockedList.add("test2");
  mockedList.clear();
  //验证是否执行了一次 add("test1") 操作
  verify(mockedList).add("test1");
  //同上面验证是否执行了一次 add("test1") 操作,默认就是 time(1)
  verify(mockedList, times(1)).add("test1");
  //验证是否执行了3次 add("test2") 操作
  //verify(mockedList, times(3)).add("test2");
  verify(mockedList).clear();
}

上面的测试用例我们运行过后是如下效果,测试用例是通过的。

2.png

当我们放开verify(mockedList, times(3)).add("test2"); 这一行代码进行运行时,我们可以看到测试用例未通过,提示的错误是我们预期执行 3 次,结果实际只执行了 2 次 add("test2") 操作。

3.png

上面的测试用例是验证对应方式的执行次数是否和预期一致,除了有准确的次数之外,还有最多,至少,从未等验证方式,如下所示:

 //精确次数
 verify(mockedList, times(3)).add("test2");
 //至少 1次
 verify(mockedList, atLeastOnce()).add("test2");
 //至少 2 次
 verify(mockedList, atLeast(2)).add("test2");
 //最多 5 次
 verify(mockedList, atMost(5)).add("test2");

测试用例 2

通过设值或者打桩的方式预设参数,如下所示,当执行 get(0) 操作时,我们通过 thenReturn()方法返回 hello,当执行 get(1) 操作时我们抛出空指针异常,运行结果如下图所示:

@Test
public void testWhen() throws Exception {
  LinkedList mockedList = mock(LinkedList.class);
  //设置值,通常被称为打桩
  when(mockedList.get(0)).thenReturn("hello");
  when(mockedList.get(1)).thenThrow(new NullPointerException());
  System.out.println(mockedList.get(0));
  //这里会打印 "null" 因为 get(2) 没有设置
  System.out.println(mockedList.get(2));
  //这里会抛 exception
  System.out.println(mockedList.get(1));
  //验证有没有执行 get(0) 操作
  verify(mockedList).get(0);
}

4.png

可以看到当我们调用 get(0)get(1) 的时候控制台成功的抛出了异常。这种方式通常被称为Stubbing,除了使用 when...thenReturn 方式之外,还有一种形式可以表达,代码如下:

@Test
public void testDoReturn() throws Exception {
  Iterator mockedList = mock(Iterator.class);
  doReturn("hello").when(mockedList).next();
  Object next = mockedList.next();
  System.out.println(next);
  doReturn("world").when(mockedList).next();
  Object next2 = mockedList.next();
  System.out.println(next2);
  //上面的过程也可以写成如下方式
  doReturn("test1", "test2").when(mockedList).next();
  Object next3 = mockedList.next();
  System.out.println(next3);
  Object next4 = mockedList.next();
  System.out.println(next4);
}

运行结果如下所示,也可以用 doThrow() 方法进行抛异常:

5.png

测试用例 3

日常开发中我们通过要保证方法的时效性,或者说我们要保证我们某个方法必须在多长时间内执行完成,这个时候我们也可以通过 mock 的方式来验证我们的方法是否满足要求。代码如下:

@Test
public void testTimeout() throws Exception {
      HttpService mock = mock(HttpService.class);
      String url = "http://www.xxx.com";
      mock.getRequest(url);
      verify(mock, timeout(100)).getRequest(url);
      //timeout时间后,用自定义的检验模式验证getRequest()
      VerificationMode customVer = new VerificationMode() {
        @Override
        public void verify(VerificationData data) {

        }

        @Override
        public VerificationMode description(String s) {
          return null;
        }
      };
      verify(mock, new Timeout(100, customVer)).getRequest(url);
}

Mockito 还有很多 API 可以使用,更多的使用方式,大家可以参考这面这个网站。https://www.tutorialspoint.com/mockito/mockito_timeouts.htm,有更详细的介绍。

6.png


Recommend

  • 22
    • www.hoohack.me 5 years ago
    • Cache

    Mockito-提高单元测试效率利器

    前言 之前在开发进行到写单元测试阶段的时候,发现要测试的方法里面是包含依赖的:外部接口RPC调用、DB调用。在某些情况下,部分依赖不稳定或者无法在测试环境调用时,会导致用例偶尔执行失败。 另外一点,很多用例...

  • 7

    一文让你快速上手 Mockito 单元测试框架 2020-05-30...

  • 7

    「测试」 - 接口测试 & mock工具Moco 当需要调用第三方HTTP接口时,别人的接口还没完成,可先根据接口定义文档,返回适当的数据,以便开发。在...

  • 418

    Starting with version 3.5.0, Mockito can now mock constructors and return a mock on every object construction. Like

  • 21

    Mockito 3.4.0 开始可 Mock 静态方法 2021-02-03 — Yanbin Java 单元测试最趁手的 Mock 组件当属 Mockito,虽然它最初是基于继承来实现  Mock 的,所以对私有方法,私有属性,静态方法,final 类,final 方法,构造函数无能为...

  • 10

    Mockito 源码分析(2)——Mock 与 SpyJitwxs|发表于2021-09-20|更新于2021-09-25|单元测试字数总计:1.3k|阅读时长:4分钟|阅读量:3

  • 13

    一文教会你mock(Mockito和PowerMock双剑合璧) 精选 原创 京东云官方 2023-01-05...

  • 7
    • www.androidchina.net 2 years ago
    • Cache

    七款最优秀的Java测试框架

    Java 是当今最流行的编程语言之一,常年位居最受欢迎编程语言排行榜前三。一个优秀的java程序员,在研发时离不开对测试框架的了解,从而开发出更安全和更高效的代码。使用这些测试框架的其中一个最重要的原因是减少出错的可能性,提高开发效率,并降低研发成本。在本...

  • 6
    • www.51cto.com 2 years ago
    • Cache

    五个优秀 Python 测试框架

    五个优秀 Python 测试框架 作者:科技狠活与软件技术 2023-03-22 18:17:49 在本文中,读者将找到用于测试自动化的前 5 个 Python 框架的真实比较。发现他们所有的优点和缺点。 在本文中,读者将找到用于...

  • 9
    • studygolang.com 2 years ago
    • Cache

    在Golang中使用Testify mock框架

    在Golang中使用Testify mock框架 guoapeng · 大约3小时之前 · 51 次点击...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK