By kswaughs | Sunday, August 23, 2015

Mock Java Objects with Mockito Framework

Mockito is a popular mock framework which can be used in conjunction with JUnit. Mockito allows you to create and configure mock objects.

Declaring a dependency to Mockito Using Maven

    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>

Using Mockito

Mockito supports the creation of mock objects with the static mock() method call. It also supports the creation of mock objects based on the @Mock annotation. If you use annotations, you must initialize this mock objects with a MockitoAnnotations.initMocks(this) method call or annotate your class with the @RunWith(MockitoJUnitRunner.class) annotation to use the Mockito test runner.

Different ways of creation of mock objects

Using Mockito.mock()
import org.junit.*;
import org.mockito.Mockito;

public class SampleTest {

     private UserService userSvc; // class to be tested

     UserDAO userDao; // dependant class to be mocked

     @Before
     public void setUp() {

          userDao = (UserDAO) Mockito.mock(UserDAO.class);

          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object
     }
}

Using annotations with initMocks
import org.junit.Before;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class SampleTest {

     private UserService userSvc; // class to be tested

     @Mock
     UserDAO  userDao;  

     @Before
     public void setUp() {
 
          MockitoAnnotations.initMocks(this);
          
          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object
     }
} 

Using annotations with MockitoJUnitRunner
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SampleTest {

     private UserService userSvc; // class to be tested

     @Mock
     UserDAO userDao;

     @Before
     public void setUp() {

          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object

     }

}

In the above samples, we have seen how to declare a mock object with mockito. Now we will see how to set the expectations on mock objects so that the mock object retuns the desired output when a method on the mock object gets executed. A complete junit test class with mockito framework looks as below

Basic structure of Junit with Mockito
import static org.junit.Assert.assertEquals;
import org.junit.*;

@RunWith(MockitoJUnitRunner.class)
public class SampleTest {

    private UserService userSvc;

    @Mock
    UserDAO  userDao; 

    @Before
    public void setUp() {
        userSvc = new UserService();
        userSvc.setUserDAO(userDao); // Stubbing the mock object
    }

    @Test 
    public void testWhenUserDetailsFound() throws Exception{  

       // Here set the expectations on mocked userDAO 
       // according to your test case scenario. 
            
       
       User user = userSvc.getUserById(“EMP341234”);
         
       assertEquals("EMP341234", user.getUserId() );
       assertEquals("JOHN", user.getUserName() );

     }  
}

Different ways of expectations supported by Mockito

Mockito.when() method is used to set expectations. Below is the import statement is required in your test class.

import  org.mockito.Mockito;

When method does not have any arguments
Class : Processor
Method : String getUserName();

Mockito.when(processor.getUserName()).thenReturn(“JOHN WOO”);   

When method has a String argument
Class : Processor
Method : String getUserName(String id);

//Case : Return the expected name for any string argument

Mockito.when(processor.getUserName(Matchers.anyString())).
      thenReturn(“JOHN WOO”);

//Case : Return the expected name for specific string argument

Mockito.when(processor.getUserName(Matchers.eq("EMP123"))).
      thenReturn(“JOHN WOO”); 

When method has user defined object as an argument
Class : Processor
Method : String getUserDetails(UserRequest req);

Mockito.when(processor.getUserName(Matchers.any (UserRequest.class))).
      thenReturn(“JOHN WOO”); 

Mock a method to throw some exception
Class : Processor
Method : String getUserDetails(UserRequest req) throws InvalidUserException

//Case : throw exception without constructing the exception object

Mockito.when(processor.getUserName(Matchers.any (UserRequest.class))).
      thenThrow(InvalidUserException.class);

//Case : throw exception with constructing the exception object

Mockito.when(processor.getUserName(Matchers.any(UserRequest.class))).
      thenThrow(new  InvalidUserException()); 

Partial Mocking

Partial mock means mock one method to return expected response and other methods to be called real ones. When you mock an object, you have to set expectations on all the methods, otherwise they will return null as their behaviour are not defined after a mock object is created. So if you want a partial mocking then use spy() method.

Mock a method with spy
Class : Processor
Method : String getUserDetails(UserRequest req) throws InvalidUserException

Processor  processor = Mockito.spy(new Processor());

// Set expectations as below like any other mocked object.

Mockito.when(processor.getUserName(Matchers.any(UserRequest.class))).
      thenThrow(new InvalidUserException());
 

Mockito limitations

With Mockito, we cannot mock the below types of classes.

1. static methods
2. final classes & methods
3. classes instantiated in a method

The solution is to use PowerMockito. 

Recommend this on


No comments:

Post a Comment