April 20, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Mockito: Java Unit Testing with Mock Objects, Page 2

  • May 14, 2010
  • By Jacek Furmankiewicz, Jacek Furmankiewicz
  • Send Email »
  • More Articles »

Creating Mock Objects

In all your JUnit test classes, make sure you do a static import of the Mockito library:

import static org.mockito.Mockito.*;


Then you can simply use the mock() method to create mock object instances.

public class PersonServiceMockTest {

private PersonService service;
private PersonDao dao; //we will be mocking this class

@Before
public void setup() {
dao = mock(PersonDao.class); //here is the actual mocking call

service = new PersonService();
service.setPersonDao(dao);
}


Verify Methods Were Called

Let's ensure that when the REST service's findAll() method is called, the corresponding DAO findAll() method is called as well. This is accomplished using intuitive Mockito methods such as when(*method*).thenReturn(*value*):

@Test
 public void testFindAll() {
 List all = new LinkedList();
 all.add(new Person(1,"John","Doe",null));
 all.add(new Person(2,"Jane","Doe",null));
 
 //MOCK ALERT: return mocked result set on find
 when(dao.findAll()).thenReturn(all); 
 
 //call the main method you want to test
 List result = service.findAll();
 
 //MOCK ALERT: verify the method was called
 verify(dao).findAll(); 
 }


The verify() method is used to verify that the mocked out method was actually called.

Test Behavior with Different Return Values from Methods

Suppose you want to test the REST service, knowing the findAll() method will return a null if no data is found in the database. You can do this easily by telling the mocked DAO to return an empty collection.

@Test
 public void testNullReturnIfNoDataFound() {
 List all = new LinkedList();
 
 //return mocked result set on find
 when(dao.findAll()).thenReturn(all);
 
 //call the main method you want to test
 List result = service.findAll();
 
 //verify the method was called
 verify(dao).findAll();
 
 //verify null result was returned
 assertEquals(null,result); 


}

Here's another sample: suppose you want to ensure that an HTTP code 200 (OK) is returned when the primary key you passed exists in the database, but a 404 is returned if it does not. With Mockito, a test is trivial:

@Test
 public void testResponsesOnFind() {
 //simulate Person ID = 1 in the DB
 when(dao.findByPrimaryKey(1)).thenReturn(new Person(1,"John","Doe",null));
 
 //test response when ID exists
 Response found = service.find(1);
 assertEquals(200, found.getStatus());
 
 //test response when ID does not exist in DB
 Response notFound = service.find(999);
 assertEquals(404, notFound.getStatus());
 }


Verify Number of Times Method Was Called

Because hitting the database is an expensive operation, you should ensure that the REST service calls the DAO only once per service call. Using Mockito's times(), atMost(), and atLeast() methods, you can test exactly how many times an expensive operation is called:

@Test
 public void testDaoCalledOnlyOnce() {
 List all = new LinkedList();
 
 //return mocked result set on find
 when(dao.findAll()).thenReturn(all);
 
 //call the main method you want to test
 service.findAll();
 
 //verify the method was called exactly once
 verify(dao,times(1)).findAll();
 verify(dao, atMost(1)).findAll();
 verify(dao, atLeast(1)).findAll();
 }


Test Error Handling

Suppose that when a DAO operation fails (e.g., database is down) the service's update() method will not propagate the exception to the client. Instead, it will return a clean JAX-RS Response object with a regular HTTP error code 500. You can simulate this behavior by telling the mock DAO to throw a RuntimeException when it gets called and verifying how the JAX-RS Web service handles it:

@Test
 public void testServerErrorReturnedOnFailedUpdate() {
 when(dao.findByPrimaryKey(1)).thenThrow(new RuntimeException("DB Failed"));
 
 Response r = service.update(1, "John","Doe","john.doe@gmail.com");
 
 assertEquals(500,r.getStatus());
 }


Summary

I have only scratched the surface of what Mockito can do. Check out their detailed documentation for more advanced samples. Understanding the importance of unit testing (and being able to use mock objects to accomplish it) is one of the critical lessons of becoming a senior Java developer. It will surely enhance your standing in a competitive job market.

Code Download

  • Mockito.zip
  • About the Author

    Jacek Furmankiewicz is a Senior Java EE, Python, Oracle and MySQL developer at Radialpoint. He has 16 years of IT experience in writing enterprise software for a wide variety of industries.



    Page 2 of 2



    Comment and Contribute

     


    (Maximum characters: 1200). You have characters left.

     

     


    Sitemap | Contact Us

    Rocket Fuel