`

mockito简单教程

 
阅读更多

官网: http://mockito.org

API文档:http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html

项目源码:https://github.com/mockito/mockito

 

首先添加maven依赖

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1.       <dependency>  
  2.           <groupId>org.mockito</groupId>  
  3.           <artifactId>mockito-all</artifactId>  
  4.           <version>1.9.5</version>  
  5.           <scope>test</scope>  
  6.       </dependency>  

 

当然mockito需要junit配合使用

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. <dependency>  
  2.   <groupId>junit</groupId>  
  3.   <artifactId>junit</artifactId>  
  4.   <version>4.11</version>  
  5.   <scope>test</scope>  
  6. </dependency>  

然后为了使代码更简洁,最好在测试类中导入静态资源

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. import static org.mockito.Mockito.*;  
  2. import static org.junit.Assert.*;  


下面我们开始使用mockito来做测试

 

1、验证行为

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void verify_behaviour(){  
  3.     //模拟创建一个List对象  
  4.     List mock = mock(List.class);  
  5.     //使用mock的对象  
  6.     mock.add(1);  
  7.     mock.clear();  
  8.     //验证add(1)和clear()行为是否发生  
  9.     verify(mock).add(1);  
  10.     verify(mock).clear();  
  11. }  


2、模拟我们所期望的结果

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void when_thenReturn(){  
  3.     //mock一个Iterator类  
  4.     Iterator iterator = mock(Iterator.class);  
  5.     //预设当iterator调用next()时第一次返回hello,第n次都返回world  
  6.     when(iterator.next()).thenReturn("hello").thenReturn("world");  
  7.     //使用mock的对象  
  8.     String result = iterator.next() + " " + iterator.next() + " " + iterator.next();  
  9.     //验证结果  
  10.     assertEquals("hello world world",result);  
  11. }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test(expected = IOException.class)  
  2. public void when_thenThrow() throws IOException {  
  3.     OutputStream outputStream = mock(OutputStream.class);  
  4.     OutputStreamWriter writer = new OutputStreamWriter(outputStream);  
  5.     //预设当流关闭时抛出异常  
  6.     doThrow(new IOException()).when(outputStream).close();  
  7.     outputStream.close();  
  8. }  


3、参数匹配

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void with_arguments(){  
  3.     Comparable comparable = mock(Comparable.class);  
  4.     //预设根据不同的参数返回不同的结果  
  5.     when(comparable.compareTo("Test")).thenReturn(1);  
  6.     when(comparable.compareTo("Omg")).thenReturn(2);  
  7.     assertEquals(1, comparable.compareTo("Test"));  
  8.     assertEquals(2, comparable.compareTo("Omg"));  
  9.     //对于没有预设的情况会返回默认值  
  10.     assertEquals(0, comparable.compareTo("Not stub"));  
  11. }  

除了匹配制定参数外,还可以匹配自己想要的任意参数

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void with_unspecified_arguments(){  
  3.     List list = mock(List.class);  
  4.     //匹配任意参数  
  5.     when(list.get(anyInt())).thenReturn(1);  
  6.     when(list.contains(argThat(new IsValid()))).thenReturn(true);  
  7.     assertEquals(1, list.get(1));  
  8.     assertEquals(1, list.get(999));  
  9.     assertTrue(list.contains(1));  
  10.     assertTrue(!list.contains(3));  
  11. }  
  12.   
  13. private class IsValid extends ArgumentMatcher<List>{  
  14.     @Override  
  15.     public boolean matches(Object o) {  
  16.         return o == 1 || o == 2;  
  17.     }  
  18. }  

需要注意的是如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void all_arguments_provided_by_matchers(){  
  3.     Comparator comparator = mock(Comparator.class);  
  4.     comparator.compare("nihao","hello");  
  5.     //如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配  
  6.     verify(comparator).compare(anyString(),eq("hello"));  
  7.     //下面的为无效的参数匹配使用  
  8.     //verify(comparator).compare(anyString(),"hello");  
  9. }  

4、验证确切的调用次数

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void verifying_number_of_invocations(){  
  3.     List list = mock(List.class);  
  4.     list.add(1);  
  5.     list.add(2);  
  6.     list.add(2);  
  7.     list.add(3);  
  8.     list.add(3);  
  9.     list.add(3);  
  10.     //验证是否被调用一次,等效于下面的times(1)  
  11.     verify(list).add(1);  
  12.     verify(list,times(1)).add(1);  
  13.     //验证是否被调用2次  
  14.     verify(list,times(2)).add(2);  
  15.     //验证是否被调用3次  
  16.     verify(list,times(3)).add(3);  
  17.     //验证是否从未被调用过  
  18.     verify(list,never()).add(4);  
  19.     //验证至少调用一次  
  20.     verify(list,atLeastOnce()).add(1);  
  21.     //验证至少调用2次  
  22.     verify(list,atLeast(2)).add(2);  
  23.     //验证至多调用3次  
  24.     verify(list,atMost(3)).add(3);  
  25. </span>}  

5、模拟方法体抛出异常

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test(expected = RuntimeException.class)  
  2. public void doThrow_when(){  
  3.     List list = mock(List.class);  
  4.     doThrow(new RuntimeException()).when(list).add(1);  
  5.     list.add(1);  
  6. }  

6、验证执行顺序

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void verification_in_order(){  
  3.     List list = mock(List.class);  
  4.     List list2 = mock(List.class);  
  5.     list.add(1);  
  6.     list2.add("hello");  
  7.     list.add(2);  
  8.     list2.add("world");  
  9.     //将需要排序的mock对象放入InOrder  
  10.     InOrder inOrder = inOrder(list,list2);  
  11.     //下面的代码不能颠倒顺序,验证执行顺序  
  12.     inOrder.verify(list).add(1);  
  13.     inOrder.verify(list2).add("hello");  
  14.     inOrder.verify(list).add(2);  
  15.     inOrder.verify(list2).add("world");  
  16. }  

7、确保模拟对象上无互动发生

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void verify_interaction(){  
  3.     List list = mock(List.class);  
  4.     List list2 = mock(List.class);  
  5.     List list3 = mock(List.class);  
  6.     list.add(1);  
  7.     verify(list).add(1);  
  8.     verify(list,never()).add(2);  
  9.     //验证零互动行为  
  10.     verifyZeroInteractions(list2,list3);  
  11. }  

8、找出冗余的互动(即未被验证到的)

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test(expected = NoInteractionsWanted.class)  
  2. public void find_redundant_interaction(){  
  3.     List list = mock(List.class);  
  4.     list.add(1);  
  5.     list.add(2);  
  6.     verify(list,times(2)).add(anyInt());  
  7.     //检查是否有未被验证的互动行为,因为add(1)和add(2)都会被上面的anyInt()验证到,所以下面的代码会通过  
  8.     verifyNoMoreInteractions(list);  
  9.   
  10.     List list2 = mock(List.class);  
  11.     list2.add(1);  
  12.     list2.add(2);  
  13.     verify(list2).add(1);  
  14.     //检查是否有未被验证的互动行为,因为add(2)没有被验证,所以下面的代码会失败抛出异常  
  15.     verifyNoMoreInteractions(list2);  
  16. }  

9、使用注解来快速模拟

 

在上面的测试中我们在每个测试方法里都mock了一个List对象,为了避免重复的mock,是测试类更具有可读性,我们可以使用下面的注解方式来快速模拟对象:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Mock  
  2. private List mockList;  

OK,我们再用注解的mock对象试试

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void shorthand(){  
  3.     mockList.add(1);  
  4.     verify(mockList).add(1);  
  5. }  

运行这个测试类你会发现报错了,mock的对象为NULL,为此我们必须在基类中添加初始化mock的代码

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class MockitoExample2 {  
  2.     @Mock  
  3.     private List mockList;  
  4.   
  5.     public MockitoExample2(){  
  6.         MockitoAnnotations.initMocks(this);  
  7.     }  
  8.   
  9.     @Test  
  10.     public void shorthand(){  
  11.         mockList.add(1);  
  12.         verify(mockList).add(1);  
  13.     }  
  14. }  

 

或者使用built-in runner:MockitoJUnitRunner

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @RunWith(MockitoJUnitRunner.class)  
  2. public class MockitoExample2 {  
  3.     @Mock  
  4.     private List mockList;  
  5.   
  6.     @Test  
  7.     public void shorthand(){  
  8.         mockList.add(1);  
  9.         verify(mockList).add(1);  
  10.     }  
  11. }  

 

更多的注解还有@Captor,@Spy,@InjectMocks

10、连续调用

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test(expected = RuntimeException.class)  
  2. public void consecutive_calls(){  
  3.     //模拟连续调用返回期望值,如果分开,则只有最后一个有效  
  4.     when(mockList.get(0)).thenReturn(0);  
  5.     when(mockList.get(0)).thenReturn(1);  
  6.     when(mockList.get(0)).thenReturn(2);  
  7.     when(mockList.get(1)).thenReturn(0).thenReturn(1).thenThrow(new RuntimeException());  
  8.     assertEquals(2,mockList.get(0));  
  9.     assertEquals(2,mockList.get(0));  
  10.     assertEquals(0,mockList.get(1));  
  11.     assertEquals(1,mockList.get(1));  
  12.     //第三次或更多调用都会抛出异常  
  13.     mockList.get(1);  
  14. }  

11、使用回调生成期望值

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void answer_with_callback(){  
  3.     //使用Answer来生成我们我们期望的返回  
  4.     when(mockList.get(anyInt())).thenAnswer(new Answer<Object>() {  
  5.         @Override  
  6.         public Object answer(InvocationOnMock invocation) throws Throwable {  
  7.             Object[] args = invocation.getArguments();  
  8.             return "hello world:"+args[0];  
  9.         }  
  10.     });  
  11.     assertEquals("hello world:0",mockList.get(0));  
  12.     assertEquals("hello world:999",mockList.get(999));  
  13. }  

12、监控真实对象

 

使用spy来监控真实的对象,需要注意的是此时我们需要谨慎的使用when-then语句,而改用do-when语句

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test(expected = IndexOutOfBoundsException.class)  
  2. public void spy_on_real_objects(){  
  3.     List list = new LinkedList();  
  4.     List spy = spy(list);  
  5.     //下面预设的spy.get(0)会报错,因为会调用真实对象的get(0),所以会抛出越界异常  
  6.     //when(spy.get(0)).thenReturn(3);  
  7.   
  8.     //使用doReturn-when可以避免when-thenReturn调用真实对象api  
  9.     doReturn(999).when(spy).get(999);  
  10.     //预设size()期望值  
  11.     when(spy.size()).thenReturn(100);  
  12.     //调用真实对象的api  
  13.     spy.add(1);  
  14.     spy.add(2);  
  15.     assertEquals(100,spy.size());  
  16.     assertEquals(1,spy.get(0));  
  17.     assertEquals(2,spy.get(1));  
  18.     verify(spy).add(1);  
  19.     verify(spy).add(2);  
  20.     assertEquals(999,spy.get(999));  
  21.     spy.get(2);  
  22. }  

13、修改对未预设的调用返回默认期望值

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void unstubbed_invocations(){  
  3.     //mock对象使用Answer来对未预设的调用返回默认期望值  
  4.     List mock = mock(List.class,new Answer() {  
  5.         @Override  
  6.         public Object answer(InvocationOnMock invocation) throws Throwable {  
  7.             return 999;  
  8.         }  
  9.     });  
  10.     //下面的get(1)没有预设,通常情况下会返回NULL,但是使用了Answer改变了默认期望值  
  11.     assertEquals(999, mock.get(1));  
  12.     //下面的size()没有预设,通常情况下会返回0,但是使用了Answer改变了默认期望值  
  13.     assertEquals(999,mock.size());  
  14. }  

14、捕获参数来进一步断言

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1.        @Test  
  2. public void capturing_args(){  
  3.     PersonDao personDao = mock(PersonDao.class);  
  4.     PersonService personService = new PersonService(personDao);  
  5.   
  6.     ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);  
  7.     personService.update(1,"jack");  
  8.     verify(personDao).update(argument.capture());  
  9.     assertEquals(1,argument.getValue().getId());  
  10.     assertEquals("jack",argument.getValue().getName());  
  11. }  
  12.   
  13.  class Person{  
  14.     private int id;  
  15.     private String name;  
  16.   
  17.     Person(int id, String name) {  
  18.         this.id = id;  
  19.         this.name = name;  
  20.     }  
  21.   
  22.     public int getId() {  
  23.         return id;  
  24.     }  
  25.   
  26.     public String getName() {  
  27.         return name;  
  28.     }  
  29. }  
  30.   
  31. interface PersonDao{  
  32.     public void update(Person person);  
  33. }  
  34.   
  35. class PersonService{  
  36.     private PersonDao personDao;  
  37.   
  38.     PersonService(PersonDao personDao) {  
  39.         this.personDao = personDao;  
  40.     }  
  41.   
  42.     public void update(int id,String name){  
  43.         personDao.update(new Person(id,name));  
  44.     }  
  45. }  

15、真实的部分mock

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void real_partial_mock(){  
  3.     //通过spy来调用真实的api  
  4.     List list = spy(new ArrayList());  
  5.     assertEquals(0,list.size());  
  6.     A a  = mock(A.class);  
  7.     //通过thenCallRealMethod来调用真实的api  
  8.     when(a.doSomething(anyInt())).thenCallRealMethod();  
  9.     assertEquals(999,a.doSomething(999));  
  10. }  
  11.   
  12.   
  13. class A{  
  14.     public int doSomething(int i){  
  15.         return i;  
  16.     }  
  17. }  

16、重置mock

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. @Test  
  2. public void reset_mock(){  
  3.     List list = mock(List.class);  
  4.     when(list.size()).thenReturn(10);  
  5.     list.add(1);  
  6.     assertEquals(10,list.size());  
  7.     //重置mock,清除所有的互动和预设  
  8.     reset(list);  
  9.     assertEquals(0,list.size());  
  10. }  

转自 http://blog.csdn.net/sdyy321/article/details/38757135

分享到:
评论

相关推荐

    MockitoTutorialForBeginners, 面向初学者的Mockito教程.zip

    MockitoTutorialForBeginners, 面向初学者的Mockito教程 面向初学者的Mockito教程对最流行的java模拟框架的专业知识安装 Eclipse,Maven 和 Java运行示例课程概述课程步骤:期望值关于 in28Minutes我们的信念。...

    模拟测试框架Mockito简明教程

    Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 JDBC 中的ResultSet 对象),用一个虚拟的对象(Mock 对象)来创建...

    mockito-core-4.0.0-API文档-中文版.zip

    赠送jar包:mockito-core-4.0.0.jar; 赠送原API文档:mockito-core-4.0.0-javadoc.jar; 赠送源代码:mockito-core-4.0.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-4.0.0.pom; 包含翻译后的API文档:...

    mockito-core-4.0.0-API文档-中英对照版.zip

    赠送jar包:mockito-core-4.0.0.jar; 赠送原API文档:mockito-core-4.0.0-javadoc.jar; 赠送源代码:mockito-core-4.0.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-4.0.0.pom; 包含翻译后的API文档:...

    mockito-jar.zip

    mockito-all-1.10.19.jar mockito-core-4.5.1.jar mockito-junit-jupiter-4.5.1.jar mockito-junit-jupiter-4.5.1-sources.jar

    Mockito for spring

    Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito for spring Mockito ...

    Mockito+Junit5测试方法实践

    内容概要:参考Mockito官方API文档,实践框架每个特性。 适合人群:Mockito入门人员以及想全面熟悉Mockito特性的人员,做到了开箱即用。 能学到什么:“Mockito 4.6.0 + Junit 5”的组合编程。 使用建议:使用前安装...

    mockito-1.9.5.zip

    mockito junit 单元测试 mockito junit 单元测试

    mockito-core-2.15.0-API文档-中文版.zip

    赠送jar包:mockito-core-2.15.0.jar; 赠送原API文档:mockito-core-2.15.0-javadoc.jar; 赠送源代码:mockito-core-2.15.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-2.15.0.pom; 包含翻译后的API文档...

    Mockito-Programming-Cookbook

    Mockito is an open source testing framework for Java released under the MIT License. The framework allows the creation of test double objects (mock objects) in automated unit tests for the purpose of ...

    mockito-1.9.0.zip

    mockito-1.9.0.zip,免费下载,需要的拿去

    mockito-core-3.8.0-API文档-中文版.zip

    赠送jar包:mockito-core-3.8.0.jar; 赠送原API文档:mockito-core-3.8.0-javadoc.jar; 赠送源代码:mockito-core-3.8.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-3.8.0.pom; 包含翻译后的API文档:...

    mockito-core-3.8.0-API文档-中英对照版.zip

    赠送jar包:mockito-core-3.8.0.jar; 赠送原API文档:mockito-core-3.8.0-javadoc.jar; 赠送源代码:mockito-core-3.8.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-3.8.0.pom; 包含翻译后的API文档:...

    powermock-api-mockito2-2.0.9-API文档-中英对照版.zip

    赠送jar包:powermock-api-mockito2-2.0.9.jar; 赠送原API文档:powermock-api-mockito2-2.0.9-javadoc.jar; 赠送源代码:powermock-api-mockito2-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-api-...

    概述 Mockito

    关 于 Mockito 的 概 述

    mockito-core-3.1.0-API文档-中英对照版.zip

    赠送jar包:mockito-core-3.1.0.jar; 赠送原API文档:mockito-core-3.1.0-javadoc.jar; 赠送源代码:mockito-core-3.1.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-3.1.0.pom; 包含翻译后的API文档:...

    mockito-core-3.12.2.jar

    mockito-core-3.12.2

    mockito-core-3.9.0-API文档-中文版.zip

    赠送jar包:mockito-core-3.9.0.jar; 赠送原API文档:mockito-core-3.9.0-javadoc.jar; 赠送源代码:mockito-core-3.9.0-sources.jar; 赠送Maven依赖信息文件:mockito-core-3.9.0.pom; 包含翻译后的API文档:...

    Junit4.12+mockito

    资源含有Junit4.12.jar和mockito的jar包以及mockito的文档

    mockito-core-3.6.0.jar

    mockito-core-3.6.0.jarmockito-core-3.6.0.jar

Global site tag (gtag.js) - Google Analytics