unit testing on the rocks!
Why mock?
Isolation
Example

    AccountController
                          HellotxtManagement
+addAccount
+deleteAccount
                         ...
...
Example

    AccountController
                          HellotxtManagement
+addAccount
+deleteAccount
                         ...
...
The no-so-good way
                              HellotxtManagement

                             ...




    HellotxtManagementMock
 void addAccount(){
    //do what I want
 }
 ..
The no-so-good way
                              HellotxtManagement

                             ...




    HellotxtManagementMock              HellotxtManagementMock2
 void addAccount(){                  void addAccount(){
    //do what I want                    //now do this
 }                                   }
 ..                                  ..
The no-so-good way
                              HellotxtManagement

                             ...




    HellotxtManagementMock              HellotxtManagementMock2      HellotxtManagementMock3
 void addAccount(){                  void addAccount(){           void addAccount(){
    //do what I want                    //now do this                //throw exception
 }                                   }                            }
 ..                                  ..                           ..
The mockito way
Test Workflow
1. Create Mock
2. Stub
3. Invoke
4. Verify
5. Assert expectations
Creating a Mock

import static org.mockito.Mockito.*;


...
// You can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
Stubbing

// stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());
What’s going on?

// following prints "first"
System.out.println(mockedList.get(0));

// following throws runtime exception
System.out.println(mockedList.get(1));

// following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
Verify

// Although it is possible to verify a stubbed invocation, usually it's
// just redundant
// If your code cares what get(0) returns then something else breaks
// (often before even verify() gets executed).
// If your code doesn't care what get(0) returns then it should not be
// stubbed. Not convinced? See here.
verify(mockedList).get(0);
What about void
       methods?
• Often void methods you just verify them.
         //create my mock and inject it to my unit under test
         DB mockedDb = mock(DB.class);
         MyThing unitUnderTest = new MyThing(mockedDb);
         	   	
         //invoke what we want to test
         unitUnderTest.doSothing();
         	   	
         //verify we didn't forget to save my stuff.
         verify(mockedDb).save();
What about void
            methods?
• Although you can also Stub them to throw
     an exception.
 @Test(expected = HorribleException.class)
 public void test3() throws Exception {
 	   	   // create my mock and inject it to my unit under test
 	   	   Oracle oracleMock = mock(Oracle.class);
 	   	   MyThing unitUnderTest = new MyThing(oracleMock);

 	    	   String paradox = "This statement is false";

 	    	   // stub
 	    	   doThrow(new HorribleException()).when(oracleMock).thinkAbout(paradox);

 	    	   unitUnderTest.askTheOracle(paradox);
 }
Argument Matchers

when(hellotxtManagementMock.addAccount(Mockito.any(Session.class), Mockito.anyString(),
	   	   	   	   	   	   	   Mockito.anyMap(), Mockito.anyString())).thenReturn(account);
Custom Argument
                  Matcher
Mockito.when(hellotxtManagementMock.getAuthenticationInfo(Mockito.argThat(new IsValidSession()),
	   	   	   	   	   	   Mockito.eq(Networks.FACEBOOK))).thenReturn(expectedResult);



                                               ...
private   class IsValidSession extends ArgumentMatcher<Session> {
	   	     @Override
	   	     public boolean matches(Object argument) {
	   	     	   return argument instanceof Session
	   	     	   	   	   && ((Session) argument).getSessionId().equals(TestValues.VALID_SESSION_ID);
	   	     }
}
Argument Capture
    ArgumentCaptor<Session> sessionCaptor = ArgumentCaptor.forClass(Session.class);
                                          ...
   ModelAndView result = accountController.addAccount(json.toString(), sessionId, deviceType,
   deviceId, networkId);

                                          ...
verify(hellotxtManagementMock).addAccount(sessionCaptor.capture(), Mockito.eq(networkId),
	   	   	   	   	   Mockito.eq(parameters), Mockito.eq(redirectUrl));

                                          ...
    assertEquals(sessionId, sessionCaptor.getValue().getSessionId());
    assertEquals(deviceType, sessionCaptor.getValue().getDevice().getType().name());
    assertEquals(deviceId, sessionCaptor.getValue().getDevice().getUid());
Basic Unit Testing with Mockito

Basic Unit Testing with Mockito

  • 1.
    unit testing onthe rocks!
  • 2.
  • 3.
  • 4.
    Example AccountController HellotxtManagement +addAccount +deleteAccount ... ...
  • 5.
    Example AccountController HellotxtManagement +addAccount +deleteAccount ... ...
  • 6.
    The no-so-good way HellotxtManagement ... HellotxtManagementMock void addAccount(){ //do what I want } ..
  • 7.
    The no-so-good way HellotxtManagement ... HellotxtManagementMock HellotxtManagementMock2 void addAccount(){ void addAccount(){ //do what I want //now do this } } .. ..
  • 8.
    The no-so-good way HellotxtManagement ... HellotxtManagementMock HellotxtManagementMock2 HellotxtManagementMock3 void addAccount(){ void addAccount(){ void addAccount(){ //do what I want //now do this //throw exception } } } .. .. ..
  • 10.
  • 11.
    Test Workflow 1. CreateMock 2. Stub 3. Invoke 4. Verify 5. Assert expectations
  • 12.
    Creating a Mock importstatic org.mockito.Mockito.*; ... // You can mock concrete classes, not only interfaces LinkedList mockedList = mock(LinkedList.class);
  • 13.
  • 14.
    What’s going on? //following prints "first" System.out.println(mockedList.get(0)); // following throws runtime exception System.out.println(mockedList.get(1)); // following prints "null" because get(999) was not stubbed System.out.println(mockedList.get(999));
  • 15.
    Verify // Although itis possible to verify a stubbed invocation, usually it's // just redundant // If your code cares what get(0) returns then something else breaks // (often before even verify() gets executed). // If your code doesn't care what get(0) returns then it should not be // stubbed. Not convinced? See here. verify(mockedList).get(0);
  • 16.
    What about void methods? • Often void methods you just verify them. //create my mock and inject it to my unit under test DB mockedDb = mock(DB.class); MyThing unitUnderTest = new MyThing(mockedDb); //invoke what we want to test unitUnderTest.doSothing(); //verify we didn't forget to save my stuff. verify(mockedDb).save();
  • 17.
    What about void methods? • Although you can also Stub them to throw an exception. @Test(expected = HorribleException.class) public void test3() throws Exception { // create my mock and inject it to my unit under test Oracle oracleMock = mock(Oracle.class); MyThing unitUnderTest = new MyThing(oracleMock); String paradox = "This statement is false"; // stub doThrow(new HorribleException()).when(oracleMock).thinkAbout(paradox); unitUnderTest.askTheOracle(paradox); }
  • 18.
  • 19.
    Custom Argument Matcher Mockito.when(hellotxtManagementMock.getAuthenticationInfo(Mockito.argThat(new IsValidSession()), Mockito.eq(Networks.FACEBOOK))).thenReturn(expectedResult); ... private class IsValidSession extends ArgumentMatcher<Session> { @Override public boolean matches(Object argument) { return argument instanceof Session && ((Session) argument).getSessionId().equals(TestValues.VALID_SESSION_ID); } }
  • 20.
    Argument Capture ArgumentCaptor<Session> sessionCaptor = ArgumentCaptor.forClass(Session.class); ... ModelAndView result = accountController.addAccount(json.toString(), sessionId, deviceType, deviceId, networkId); ... verify(hellotxtManagementMock).addAccount(sessionCaptor.capture(), Mockito.eq(networkId), Mockito.eq(parameters), Mockito.eq(redirectUrl)); ... assertEquals(sessionId, sessionCaptor.getValue().getSessionId()); assertEquals(deviceType, sessionCaptor.getValue().getDevice().getType().name()); assertEquals(deviceId, sessionCaptor.getValue().getDevice().getUid());