mockito使用

mockito学习资料:html

http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.htmljava

http://blog.csdn.net/sdyy321/article/details/38757135函数

 

一、验证行为是否发生学习

1
2
3
4
5
6
7
8
@Test
public  void  mockedList(){
     List mockedList = mock(List. class );
     mockedList.add( "one" );
     mockedList.clear();
     verify(mockedList).add( "one" );
     verify(mockedList).clear();
}

验证add和clear是否执行。ui

二、验证返回值google

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
     public  void  two(){
         //模拟建立一个List对象
         LinkedList mockLinkedList = mock(LinkedList. class );
 
         //打桩,当LinkedList调用get(0)方法时,第一次返回zero,第二次n次返回nnnn
         when(mockLinkedList.get( 0 )).thenReturn( "zero" ).thenReturn( "nnnn" );
 
         //使用mock对象
         System.out.println(mockLinkedList.get( 0 ));
         System.out.println(mockLinkedList.get( 0 ));
         System.out.println(mockLinkedList.get( 0 ));
 
         //验证行为get是否发生
         verify(mockLinkedList).get( 0 );
 
     }

这里注意全部的方法都会有返回值,若是没有设置返回值,那么就会返回null或者空集、适当的类型。 Stubbing能够被重写,也就是同一个参数方法能够放回不一样的值,可是已最后一次设置的值为标准。一旦被 Stubbed,不管方法被调用多少次,都只会返回Stubbed value。最后一次最重要原则。spa

三、参数匹配.net

经过equals()来验证参数。rest

不一样的参数返回不一样的结果:code

1
2
when(comparable.compareTo( "Test" )).thenReturn( 1 ); 
when(comparable.compareTo( "Omg" )).thenReturn( 2 );

一旦你使用了参数匹配器,那么全部的参数都必须由匹配器给出:

1
2
3
4
5
6
7
8
9
10
11
//stubbing using built-in anyInt() argument matcher
  when(mockedList.get(anyInt())).thenReturn( "element" );
 
  //stubbing using hamcrest (let's say isValid() returns your own hamcrest matcher):
  when(mockedList.contains(argThat(isValid()))).thenReturn( "element" );
 
  //following prints "element"
  System.out.println(mockedList.get( 999 ));
 
  //you can also verify using an argument matcher
  verify(mockedList).get(anyInt());
1
2
3
4
5
verify(mock).someMethod(anyInt(), anyString(), eq( "third argument" ));
    //above is correct - eq() is also an argument matcher
 
    verify(mock).someMethod(anyInt(), anyString(),  "third argument" );
    //above is incorrect - exception will be thrown because third argument is given without an argument matcher.

四、验证调用次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Test
     public  void  three(){
         List mockedList = mock(List. class );
         mockedList.add( 1 );
         mockedList.add( 2 );
         mockedList.add( 2 );
         mockedList.add( 3 );
         mockedList.add( 3 );
         mockedList.add( 3 );
         //验证是否被调用一次,等效于下面的times(1),默认的,能够不写
         verify(mockedList).add( 1 );
         verify(mockedList,times( 1 )).add( 1 );
         //验证是否被调用2次 
         verify(mockedList,times( 2 )).add( 2 );
         //验证是否被调用3次 
         verify(mockedList,times( 3 )).add( 3 );
         //验证是否从未被调用过
         verify(mockedList,never()).add( 4 );
         //验证至少调用一次
         verify(mockedList,atLeastOnce()).add( 1 );
         //验证至少调用2次
         verify(mockedList,atLeast( 2 )).add( 2 );
         //验证至多调用3次
         verify(mockedList,atMost( 3 )).add( 3 );
     }

add(1)这个方法被调用了1次,add(2)这个被调用了2次。add(3)这个方法被调用了3次,若是将verify(mockedList,times(1)).add(3);运行后那么就会出现错误:

五、模拟方法体抛出异常

1
2
3
4
5
6
doThrow( new  RuntimeException()).when(mockedList).clear(); 
   //following throws RuntimeException:
mockedList.clear();
 
doThrow( new  RuntimeException()).when(list).add( 1 ); 
list.add( 1 );

六、验证执行的顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
     public  void  four(){
         List firstList = mock(List. class );
         List secondList = mock(List. class );
         //using mocks
         firstList.add( "was called first one mock" );
         secondList.add( "was called second one mock" );
         //create inOrder object passing any mocks that need to be verified in order
         InOrder indOrder = inOrder(firstList,secondList);
 
         indOrder.verify(firstList).add( "was called first one mock" );
         indOrder.verify(secondList).add( "was called second one mock" );
 
 
     }

若是将11,12调换,

indOrder.verify(secondList).add("was called second one mock");

indOrder.verify(firstList).add("was called first one mock");

会出现以下错误:

但是若是顺序以下:

1
2
3
4
5
firstList.add( "was called first one mock" );
secondList.add( "was called second one mock" );
InOrder indOrder = inOrder(secondList,firstList);
indOrder.verify(firstList).add( "was called first one mock" );
indOrder.verify(secondList).add( "was called second one mock" );

inorder中顺序调换后,上面程序竟然没有出错?难道我理解错了。验证的顺序是按照inOrder中给出的,也就是second要在first前面,而在verify中明显second在first后验证了,应该出错啊。

七、模拟对象上没有相互关系

 

1
2
3
4
5
6
7
8
9
10
11
//using mocks - only mockOne is interacted
  mockOne.add( "one" );
 
  //ordinary verification
  verify(mockOne).add( "one" );
 
  //verify that method was never called on a mock
  verify(mockOne, never()).add( "two" );
 
  //verify that other mocks were not interacted
  verifyZeroInteractions(mockTwo, mockThree);

八、找出多余的调用

1
2
3
4
5
6
7
8
9
10
11
12
//using mocks
  mockedList.add( "one" );
  mockedList.add( "two" );
 
  verify(mockedList).add( "one" );
 
  //following verification will fail 检查是否有未被验证的行为
  verifyNoMoreInteractions(mockedList);
 
   verify(list,times( 2 )).add(anyInt()); 
//检查是否有未被验证的互动行为,由于add(1)和add(2)都会被上面的anyInt()验证到,因此下面的代码会经过 
    verifyNoMoreInteractions(list);

mockedList还有add("two")没有验证,因此出错。

九、使用注解来mock

这里注意要在构造函数中初试化mock对象,不然mock对象为null。

也能够经过在类上使用注解:@RunWith(MockitoJUnitRunner.class)  

这样就不须要初始化mock了。

十、连续调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test (expected = RuntimeException. class
     public  void  consecutive_calls(){ 
         List mockList = mock(List. class );
         //模拟连续调用返回指望值,若是分开,则只有最后一个有效 
         when(mockList.get( 0 )).thenReturn( 0 ); 
         when(mockList.get( 0 )).thenReturn( 1 ); 
         when(mockList.get( 0 )).thenReturn( 2 ); 
         when(mockList.get( 1 )).thenReturn( 0 ).thenReturn( 1 ).thenThrow( new  RuntimeException()); 
         assertEquals( 2 ,mockList.get( 0 )); 
         assertEquals( 2 ,mockList.get( 0 )); 
         assertEquals( 0 ,mockList.get( 1 )); 
         assertEquals( 1 ,mockList.get( 1 )); 
         //第三次或更多调用都会抛出异常 
         mockList.get( 1 ); 
     }

十一、使用回调来stub

通用:

1
2
3
4
5
6
7
8
9
10
when(mock.someMethod(anyString())).thenAnswer( new  Answer() {
      Object answer(InvocationOnMock invocation) {
          Object[] args = invocation.getArguments();
          Object mock = invocation.getMock();
          return  "called with arguments: "  + args;
      }
  });
  
  //Following prints "called with arguments: foo"
  System.out.println(mock.someMethod( "foo" ));

使用:

1
2
3
4
5
6
7
8
9
10
11
12
@Test
     public  void  six(){
         List mockList = mock(List. class );
         when(mockList.get(anyInt())).thenAnswer( new  Answer<Object>() {
             public  Object answer(InvocationOnMock invocation)  throws  Throwable {
                 Object[] args = invocation.getArguments();
                 return  "hi:" +args[ 0 ];
             }
         });
         assertEquals( "hi:0" ,mockList.get( 0 ));
         assertEquals( "hi:1" ,mockList.get( 1 ));
     }

十二、对于void方法,有系列函数能够用来处理。

doThrow() doAnswer doNothing doReturn。当一个void的方法有异常抛出时可使用doThrow()。

1三、监控真实对象

当使用spy的时候真正的方法将会被调用,而再也不是stub的对象了,这个和部分mock的思想是同样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
     public  void  seven(){
         List list =  new  LinkedList();
         List spy = spy(list);
          
         //optionally, you can stub out some methods:
         when(spy.size()).thenReturn( 100 );
          
         //using the spy calls real methods
         spy.add( "one" );
         spy.add( "two" );
          
         //prints "one" - the first element of a list
         System.out.println(spy.get( 0 ));
          
         //size() method was stubbed - 100 is printed
          System.out.println(spy.size());
          
         //optionally, you can verify
         verify(spy).add( "one" );
         verify(spy).add( "two" );
     }

使用spy的时候须要注意一点:有时候是不能使用when语句的

1
2
3
4
5
6
7
8
List list =  new  LinkedList();
    List spy = spy(list);
    
    //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
    when(spy.get( 0 )).thenReturn( "foo" );
    
    //You have to use doReturn() for stubbing
    doReturn( "foo" ).when(spy).get( 0 );

1四、设置未stub的调用的默认值

对于没有stub方法的调用,咱们通常返回null,或者是默认类型。也能够修改使其返回你指定的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test 
     public  void  eight(){ 
         //mock对象使用Answer来对未预设的调用返回默认指望值 
         List mocklist = mock(List. class , new  Answer(){ 
             public  Object answer(InvocationOnMock invocation)  throws  Throwable { 
                 return  999
             }
         }); 
         //下面的get(1)没有预设,一般状况下会返回NULL,可是使用了Answer改变了默认指望值 
         assertEquals( 999 , mocklist.get( 1 )); 
         //下面的size()没有预设,一般状况下会返回0,可是使用了Answer改变了默认指望值 
         assertEquals( 999 ,mocklist.size()); 
     }
相关文章
相关标签/搜索