ICE09 . playing with java, scala, groovy and spring .

Playing with Spring

Mocking and Stubbing with Mockito

Posted by ice09 on January 9, 2011

 

Intention

Let’s assume there is a new requirement for an existing CRM-like system: send a mail to all customers with a balance greater than 1000. Since we are not allowed to access the database directly, we will have to use existing services.

image

Since we are using Spring, the configuration is obvious, the services are injected, that’s it.

Mocking

However, for testing purposes, we want to mock the services. By examining the classes and methods, we will see why mocking is necessary, but not enough in this case.

Setup

Only the interfaces of the services are shown, they are mocked anyway.

MailService

 
public interface MailService { 
    
    void sendMails(List<customer> customers); 

}

CustomerDao

 
public interface CustomerDao { 

    List<customer> getCustomers(); 

} 

This is the class under test, the filter method should be tested.

 
public class CustomerService { 
    
    private CustomerDao customerDao; 
    private MailService mailService; 
    
    public void notifyCustomersWithBalanceGreaterThan(long cbalance) { 
        List<customer> notificationList = new ArrayList<customer>(); 
        List<customer> customers = customerDao.getCustomers(); 
        for (Customer customer : customers) { 
            if (customer.getBalance() > cbalance) { 
                notificationList.add(customer); 
            } 
        }
        mailService.sendMails(notificationList); 
    } 

} 

Testing…

How do we test if everything worked? There is no result object to check, since mails are sent. Here mocking comes into play, a breeze with Mockito.

 
@RunWith(MockitoJUnitRunner.class)
public class TestClass {

	private @Mock CustomerDao customerDao;
	private @Mock MailService mailService;
	
	private @InjectMocks CustomerService customerService = new CustomerService();

	private @Captor ArgumentCaptor<List<Customer>> customerCaptor;

	@Before
	public void setup() {
		MockitoAnnotations.initMocks(this);
	}

	@Test
	public void testIt() {
		//preparation (stubbing)
		when(customerDao.getCustomers()).thenReturn(prepareList());
		
		customerService.notifyCustomersWithBalanceGreaterThan(1000);

		//verification (mocking)
		//has customerDao be called correctly?
		verify(customerDao, times(1)).getCustomers();
		verifyNoMoreInteractions(customerDao);

		//have the mails be sent?
		verify(mailService).sendMails(customerCaptor.capture());
		
		//is the list of customers to notify correct? 
		assertEquals(2, customerCaptor.getValue().size());
		assertEquals(new Customer(3, "eva", "mustermann", 2000), customerCaptor.getValue().get(0)); 
		assertEquals(new Customer(6, "hanna", "mustermann", 1001), customerCaptor.getValue().get(1)); 
		verifyNoMoreInteractions(mailService);
	}

	private List<Customer> prepareList() {
		List<Customer> customers = new ArrayList<Customer>();
		customers.add(new Customer(1, "hans", "mustermann", 100));
		customers.add(new Customer(2, "max", "mustermann", 1000));
		customers.add(new Customer(3, "eva", "mustermann", 2000));
		customers.add(new Customer(4, "anna", "mustermann", 0));
		customers.add(new Customer(6, "hanna", "mustermann", 1001));
		return customers;
	}

}

The mocking part is straightforward. However, we have to stub as well, since we want the CustomerDao to actually return our prepared Customer list. No problem with Mockito (search for Test Spy to see why there are differences in Mocking frameworks regarding the support of Mocking, Stubbing or both – then being a Test Spy).

Dependency injection

Really interesting is the wiring of the components. The MockitoJUnitRunner.class is used to run the Unittest, we do not use Spring for this test. But magically, after calling MockitoAnnotations.initMocks(this) the @Mock annotated Mocks are injected into the @InjectMocks annotated class automatically. This being great already, we are furthermore using the @Captor annotation to create a argument captor for all List arguments. Now we can examine the submitted list with Customers to sent mail to and determine, if the correct Customers have been filtered.
So, we have a nice dependency injection, combined with stubbing and mocking. Mockito is really powerful (and much easier to use than similar Mocking frameworks), you can even partially stub objects. However, there should be a really good reason for doing this…

Advertisements

One Response to “Mocking and Stubbing with Mockito”

  1. […] ICE09: Mocking and Stubbing with Mockito […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: