Wednesday, 19 September 2012

TDD with Mockito

You may not be getting the most out of your TDD and JUnit, Mockito is an effective mocking framework that works great.

Mockito Verify

Verify allows you to set up expectations on the mock methods that are 'probed' by the test case in a whitebox manner.
@Test  
public void testMockitoVerify()  
{  
    //mock creation  
    List<String> mockedList = mock(List.class);  
    //using mock object  
    mockedList.add("one");  
    mockedList.clear();  
    //verification  
    verify(mockedList).add("one");  
    verify(mockedList).clear();  
}  

Mockito Stubbing (toReturn, toThrow)

Mockito also supports stubs by allowing you to specify return values when certain methods are called. Once stubbed, the method will always return stubbed value regardless of how many times it is called.
@Test  
public void testMockitoStubbing()  
{  
     //You can mock concrete classes, not only interfaces  
     LinkedList mockedList = mock(LinkedList.class);  
     //stubbing  
     stub(mockedList.get(0)).toReturn("first");  
     stub(mockedList.get(1)).toThrow(new RuntimeException());  
     //following prints "first"  
     System.out.println(mockedList.get(0));  
     //following prints "null" because get(999) was not stubbed  
     System.out.println(mockedList.get(999));           
}  

Mockito Invocations (times, atLeast, atMost)

You can verify a certain number of calls by using times for an exact number of calls, atMost for upto a number and atLeast for above a number. 
@Test  
public void testMockitoInvocations()  
{  
    //mock creation  
    List<String> mockedList = mock(List.class);  
    //using mock  
    mockedList.add("once");  
    mockedList.add("three times");  
    mockedList.add("three times");  
    mockedList.add("three times");  
    //verification, times(1) is used by default  
    verify(mockedList).add("once");  
    //verification using never(). never() is an alias to times(0)  
    verify(mockedList, never()).add("never happened");  
    //verification using atLeast()  
    verify(mockedList, atLeastOnce()).add("three times");  
    verify(mockedList, times(3)).add("three times");  
    //verify using atMost  
    verify(mockedList, atMost(3)).add("three times");  
} 

Mockito Whitebox (when / thenReturn)

You can specify mock return values using when and thenReturn.
@Test  
public void testMockitoWhitebox() {  
    //mock creation  
    Calendar mock = mock(Calendar.class);  
    TimeZone tz = mock(TimeZone.class);  
    when(mock.getTimeZone()).thenReturn(tz);  
    when(tz.getID()).thenReturn("PST");  
    String result = mock.getTimeZone().getID();  
    assertEquals("PST", result);  
}  

Mockito Throws

You can set up exception throwing behaviour for you mocks using doThrow.  
@Test(expected = RuntimeException.class)   
public void testMockitoThrows() {  
    //mock creation  
    List<String> mockedList = mock(List.class);  
    doThrow(new RuntimeException()).when(mockedList).clear();        
    mockedList.clear();  
} 

Mockito Verification Equals

You can verify mock method parameters using eq.
@Test
public void testMockitoEq() {  
    //mock creation  
    List mock = mock(List.class);  
    mock.add("test");  
    verify(mock).add(eq("test"));  
}  

Mockito Verification Any

If you do not care to verify a specific parameter values being passed to a mock you can use 'any'.
@Test
public void testMockitoAny() {  
    //mock creation  
    List<String> mockedList = mock(List.class);  
    mockedList.add("test");  
    verify(mockedList).add(any(String.class));  
    verify(mockedList).add((String)anyObject());  
}  

Mockito Verification ArgThat

If you want to use a custom matcher to verify an argument then you can use argThat.
@Test  
public void testMockitoArgThat() throws IOException{          
    OutputStream mock=mock(OutputStream.class);  
    OutputStreamWriter osw=new OutputStreamWriter(mock);  
    osw.write('a');  
    osw.flush();  
    // can't do this as we don't know how long the array is going to be  
    // verify(mock).write(new byte[]{'a'},0,1);  
    BaseMatcher arrayStartingWithA=new BaseMatcher(){  
        @Override  
        public void describeTo(Description description) {  
            // nothing  
        }  
        // check that first character is A  
        @Override  
        public boolean matches(Object item) {  
            byte[] actual=(byte[]) item;  
            return actual[0]=='a';  
        } 
    };  
    // check that first character of the array is A, 
    // and that the other two arguments are 0 and 1  
    verify(mock).write((byte[]) argThat(arrayStartingWithA), eq(0),eq(1));      
}  

You can get Mockito here.
Example source here.

No comments:

Post a Comment