Mockito(三)--完整功能介绍
编程技术  /  houtizong 发布于 3年前   59
mockito官网:http://code.google.com/p/mockito/,打开documentation可以看到官方最新的文档资料。
一.使用mockito验证行为
//首先要import Mockitoimport static org.mockito.Mockito.*;//mock creationList mockedList = mock(List.class);//using mock objectmockedList.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知道前面是否调用过某方法。
二.使方法调用返回期望的值,也被称为stubbing
//You can mock concrete classes, not only interfacesLinkedList 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 exceptionSystem.out.println(mockedList.get(1));//following prints "null" because get(999) was not stubbedSystem.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"。
三.参数匹配
在上例中如果想实现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 { //首先mock File类 File mock = mock(File.class); //注意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> { //这里的macther不仅可以匹配任意的SOAPMessage对象,如果输入参数为空也可以匹配上。 public boolean matches(Object soapMessage) { return (soapMessage instanceof SOAPMessage) || soapMessage==null; }}
做参数匹配的时候,需考虑到输入参数为空的情况,因为如果为空,会导致matcher匹配不上,进而stub的行为无法生效。
发现mock对象没有想自己想象的方式工作时,最好的方法就是debug进去,首先要先确定mock对象是不是真的传递进去了,然后再一步步的debug。通常遇到的两种情况就是:1.mock对象没有传递进去;2.参数没有匹配上。
四.验证方法被调用了特定次数/至少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");
五.调用方法时抛出异常
doThrow(new RuntimeException()).when(mockedList).clear();
六.验证顺序
//下面的代码验证firstMock先被调用,secondMock后被调用。inOrder.verify(firstMock).add("was called first");inOrder.verify(secondMock).add("was called second");
七.验证mock之间没有相互作用
八.找到冗余的调用
用never()就可以实现,不多说。
九.使用@mock 定义mock
之前都是使用mock()来模拟一个对象,用@mock是一个shorthand。
public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; private ArticleManager manager;}
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接