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()); 
     }
相關文章
相關標籤/搜索