博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Mockito入门
阅读量:6221 次
发布时间:2019-06-21

本文共 7137 字,大约阅读时间需要 23 分钟。

hot3.png

logo

简介

使用Mock总来说只有四步操作:

  1. mock creation
  2. stub method calls
  3. Use mock object
  4. verify interactions

声明mockito依赖

org.mockito
mockito-all
LATEST

1.验证行为

一旦创建 mock 将会记得所有的交互。你可以选择验证你感兴趣的任何交互

//Let's import Mockito statically so that the code looks clearerimport static org.mockito.Mockito.*;//mock creationList mockedList = mock(List.class);//using mock objectmockedList.add("one");mockedList.clear();//verificationverify(mockedList).add("one");verify(mockedList).clear();

2.stubbing

  • 默认情况下,所有方法都会返回值,一个 mock 将返回要么 null,一个原始/基本类型的包装值或适当的空集。例如,对于一个 int/Integer 就是 0,而对于 boolean/Boolean 就是 false。
  • Stubbing 可以被覆盖。
  • 一旦 stub,该方法将始终返回一个 stub 的值,无论它有多少次被调用。
  • 最后的 stubbing 是很重要的 - 当你使用相同的参数 stub 多次同样的方法。换句话说:stubbing 的顺序是重要的,但它唯一有意义的却很少,例如当 stubbing 完全相同的方法调用,或者有时当参数匹配器的使用,等等。
//You can mock concrete classes, not just interfaces LinkedList mockedList = mock(LinkedList.class); //stubbing 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)); //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). //If your code doesn't care what get(0) returns, then it should not be stubbed. Not convinced? See here. verify(mockedList).get(0);

3.参数匹配器

Mockito 验证参数值使用 Java 方式:通过使用 equals() 方法。有时,当需要额外的灵活性,可以使用参数匹配器

参数匹配器允许灵活的验证或 stubbing。点击 查看更多内置的匹配器和自定义的参数匹配器/ hamcrest匹配器的例子。

自定义参数的匹配信息,请查看 Javadoc 中 类。

如果你正在使用参数的匹配,所有的参数都由匹配器来提供。

//stubbing using built-in anyInt() argument matcherwhen(mockedList.get(anyInt())).thenReturn("element");//stubbing using custom matcher (let's say isValid() returns your own matcher implementation):when(mockedList.contains(argThat(isValid()))).thenReturn("element");//following prints "element"System.out.println(mockedList.get(999));//you can also verify using an argument matcherverify(mockedList).get(anyInt());
verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));//above is correct - eq() is also an argument matcherverify(mock).someMethod(anyInt(), anyString(), "third argument");//above is incorrect - exception will be thrown because third argument is given without an argument matcher.

4.调用额外的调用数字/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 defaultverify(mockedList).add("once");verify(mockedList, times(1)).add("once");//exact number of invocations verificationverify(mockedList, times(2)).add("twice");verify(mockedList, times(3)).add("three times");//verification using never(). never() is an alias to times(0)verify(mockedList, never()).add("never happened");//verification using atLeast()/atMost()verify(mockedList, atLeastOnce()).add("three times");verify(mockedList, atLeast(2)).add("three times");verify(mockedList, atMost(5)).add("three times");

5.Stubbing void 方法处理异常

doThrow(new RuntimeException()).when(mockedList).clear();//following throws RuntimeException:mockedList.clear();

6.有序的验证

有序验证是为了灵活 - 你不必一个接一个验证所有的交互。

此外,您还可以通过创建 InOrder 对象传递只与有序验证相关的 mock 。

// A. Single mock whose methods must be invoked in a particular orderList singleMock = mock(List.class);//using a single mocksingleMock.add("was added first");singleMock.add("was added second");//create an inOrder verifier for a single mockInOrder inOrder = inOrder(singleMock);//following will make sure that add is first called with "was added first, then with "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 orderList 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 orderInOrder inOrder = inOrder(firstMock, secondMock);//following will make sure that firstMock was called before secondMockinOrder.verify(firstMock).add("was called first");inOrder.verify(secondMock).add("was called second");// Oh, and A + B can be mixed together at will

7.确保 mock 上不会发生交互

//using mocks - only mockOne is interactedmockOne.add("one");//ordinary verificationverify(mockOne).add("one");//verify that method was never called on a mockverify(mockOne, never()).add("two");//verify that other mocks were not interactedverifyZeroInteractions(mockTwo, mockThree);

8.寻找多余的调用

注意:不建议 verifyNoMoreInteractions() 在每个测试方法中使用。 verifyNoMoreInteractions() 是从交互测试工具包一个方便的断言。只有与它的相关时才使用它。滥用它导致难以维护。

//using mocksmockedList.add("one");mockedList.add("two");verify(mockedList).add("one");//following verification will failverifyNoMoreInteractions(mockedList);

9.标准创建 mock 方式 - 使用 @Mock 注解

  • 最小化可重用 mock 创建代码

  • 使测试类更加可读性

  • 使验证错误更加易读,因为字段名称用于唯一识别 mock

public class ArticleManagerTest {    @Mock private ArticleCalculator calculator;    @Mock private ArticleDatabase database;    @Mock private UserProvider userProvider;    private ArticleManager manager;}

在基础类或者测试 runner 里面,使用如下:

MockitoAnnotations.initMocks(testClass);

可以使用内建 runner: 或者 rule:

更多详见

10. Stubbing 连续调用(迭代器式的 stubbing)

when(mock.someMethod("some arg")) .thenThrow(new RuntimeException()) .thenReturn("foo");//First call: throws runtime exception:mock.someMethod("some arg");//Second call: prints "foo"System.out.println(mock.someMethod("some arg"));//Any consecutive call: prints "foo" as well (last stubbing wins).System.out.println(mock.someMethod("some arg"));

下面是一个精简版本:

when(mock.someMethod("some arg")) .thenReturn("one", "two", "three");

11.回调 Stubbing

允许使用泛型 接口。

然而,这是不包括在最初的 Mockito 另一个有争议的功能。我们建议您只需用thenReturn() 或 thenThrow() 来 stubbing ,这在测试/测试驱动中应用简洁与简单的代码足够了。但是,如果你有一个需要 stub 到泛型 Answer 接口,这里是一个例子:

when(mock.someMethod(anyString())).thenAnswer(new Answer() {   Object answer(InvocationOnMock invocation) {       Object[] args = invocation.getArguments();       Object mock = invocation.getMock();       return "called with arguments: " + args;   }});//the following prints "called with arguments: foo"System.out.println(mock.someMethod("foo"));

12.doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() 家族方法

Stubbing void 方法,需要不同的 when(Object) ,因为编译器不喜欢括号内无效的方法...

在 用于 Stubbing void 方法中,doThrow(Throwable...) 取代 stubVoid(Object)。主要原因是提高可读性和与 doAnswer() 保持一致性。

当你想用 stub void 方法 使用 doThrow():

doThrow(new RuntimeException()).when(mockedList).clear();//following throws RuntimeException:mockedList.clear();

在调用 when() 的相应地方可以使用 oThrow(), doAnswer(), doNothing(), doReturn() 和 doCallRealMethod(),当:

  • stub void 方法
  • stub 方法在 spy 对象(见下面)
  • 可以不止一次的 stub 相同的方法,在测试的中期来改变 mock 的行为

但你更加倾向于使用这些方法来代替 when(),在所有的 stubbing 调用。可以阅读更多关于这些方法的描述:

参考

转载于:https://my.oschina.net/xjt2014/blog/884898

你可能感兴趣的文章
MSSQL Rebuild(重建)索引
查看>>
Linux_CentOS-服务器搭建 <七>
查看>>
转载:mysql如果数据不存在,则插入新数据,否则更新的实现方法
查看>>
<转>多线程中的lua同步问题
查看>>
转oracle 学习- 数据类型
查看>>
Eclipse安装插件支持jQuery智能提示
查看>>
cidaemon.exe进程cpu占用率高及关闭cidaemon.exe进程方法
查看>>
C语言课程设计—图书管理系统
查看>>
iOS 多线程
查看>>
【BZOJ】1096: [ZJOI2007]仓库建设(dp+斜率优化)
查看>>
SQL删除重复数据方法
查看>>
C#资源文件与与资源名称字符串之间的互相转化
查看>>
[Unity][Heap sort]用Unity动态演示堆排序的过程(How Heap Sort Works)
查看>>
调试项目出错------360云盘同步搞的鬼
查看>>
sqlite建表语句(特别是外键问题)
查看>>
Android 刷新下拉控制 SwipeRefreshLayout
查看>>
Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件(转)
查看>>
持久化框架Hibernate 开发实例(一)
查看>>
CentOS下php安装mcrypt扩展
查看>>
2015.10.14-TransactionScope测试
查看>>