Unit Testing with Mockito

The next step in testing is to target the service layer and all the helpers, utilities or one-offs. The goal of unit testing is to test each method or path in isolation. Complications can arise when a method depends on other classes or even worse, external resources. This is where Mockito comes into play. It will allow you to completely mock a class or interface either inline or with Spring DI. Of course you could always stub it yourself but I generally only advocate that in special cases.

Getting Ready

Application Setup
These tests are built on the Spring Data JPA example in a previous post.

For this test we add a few dependencies to the pom.xml

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

<!-- Optional -->
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

mockito-all is what you need. In past usages I have seen conflicts with JUnit and hamcrest. If you see those errors try adding these additional dependencies.

Reference Class

Below is the main Service method we are testing for reference:

@Service
public class SampleServiceImpl implements SampleService {

    private UserDao userDao;

    @Autowired
    public SampleServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    public SignupForm saveFrom(SignupForm signupForm) throws InvalidUserException{

        String firstName = signupForm.getFirstName();

        if(!StringUtils.isEmpty(firstName) && "Dave".equalsIgnoreCase(firstName)) {
            throw new InvalidUserException("Sorry Dave");
        }

        User user = new User();
        user.setFirstName(signupForm.getFirstName());
        user.setEmail(signupForm.getEmail());
        user.setLastName(signupForm.getLastName());

        user = userDao.save(user);

        signupForm.setId(user.getId());

        return signupForm;
    }
}

Create the Test with Mockito

Now it’s time to create the test class “com.luckyryan.sample.service.SampleServiceTest”. The service only has one method saveForm so that’s the test I will start with. SampleService depends on UserDao which is just an interface to the DB so that is the mock target.

public class SampleServiceTest {

    private UserDao userDao;
    private SampleService sampleService;

    @Before
    public void doSetup() {
        userDao = mock(UserDao.class);
        sampleService = new SampleServiceImpl(userDao);
    }
}

So far we are using global fields and instantiating them before the Test methods. SampleService is the test target so we use the real class. It has been setup to take dependencies in the constructor. For multiple dependencies or a class that just needs one for a test then using property or method setting would also work. mock(Class) (mock() is a static import) will create a mocked version of UserDao. At this point it has no instructions so it won’t actually mock anything yet but it’s created and assigned to sampleService. The way Mockito works allows you access to the mocked class at any time and assign mock rules. This makes it really nice to do the setup here and the config in the actual test method where it makes sense.

So let’s add the first test

@Test
   public void testSaveForm() {

       SignupForm signupForm = new SignupForm();
       signupForm.setLastName("formLast");
       signupForm.setFirstName("formFirst");
       signupForm.setEmail("form@test.com");

       when(userDao.save(any(User.class)))
               .thenAnswer(new Answer<User>() {
                   @Override
                   public User answer(InvocationOnMock invocation) throws Throwable {
                       User user = (User) invocation.getArguments()[0];
                       user.setId(1L);
                       return user;
                   }
               });

       assertNull(signupForm.getId());

       signupForm = sampleService.saveFrom(signupForm);

       assertNotNull(signupForm.getId());
       assertTrue(signupForm.getId() > 0);
   }

The test starts with setting up a SignupForm. This object work is normally submitted from the web as params and converted to an object in the controller. But since this is a test for the service, we just create what is necessary to call the sampleService.saveForm() method directly.

Next we define the desired behavior of the mocked dao. “when” (also a static import) tells Mockito to listen for a call and take over when the condition is met. In this case we are watching the method userDao.save(and object of type User). You can get fancy here and change the method argument of the mocked class to match conditions to provide desired responses. For example:


// Normal save, return id
when(someDao.save("first")).thenReturn(1);

// Another save but return a different id
when(someDao.save("second")).thenReturn(2);

// Get exception
when(someDao.save("third")).thenThrow(new DataAccessException("this is expected for third"));

For our test case I chose a different route. As you can see from the test, I pass in a SignupForm, but the userDao expects a User object. That translation happens in the service and I won’t have access to that object from the test. So I just tell the mock to catch the save call for any User object. I could try to be more specific but it’s not necessary since I am only calling it once in this test. Plus if I wanted a different response then I would create a second test.

So now Mockito will intercept the call and we need to tell it what to do with it. The examples above use the common simple options like “thenReturn” or “thenThrow”. Our test case needs a little more help because the service expects a saved User object which it will use the Id field and set it back on the SignupForm (I know… it might be a code smell here but it makes for a better example).

Mockito also offers a “thenAnswer” method. This can be used to alter the incoming object (via param) and pass it back. This is very powerful and you can do some crazy stuff with it but that’s for another topic.

Now to the good part, Asserts!!!


assertNull(signupForm.getId());

signupForm = sampleService.saveFrom(signupForm);

assertNotNull(signupForm.getId());
assertTrue(signupForm.getId() > 0);



We check that the id is null on our test created object, call the service with the mocked UserDao, then assert that it and id was assigned to our object.

<h2>Validate then More Testing...</h2>

Run it and bask in the green glow from the IDE. Or if you are a command line junky then take an ego boost from the SUCCESS message. But this is just the happy path and all the service throws is an exception for Dave. So being a good tester it's time to test that path. 



@Test(expected = InvalidUserException.class)
public void testInvalidUserException() {
    SignupForm signupForm = new SignupForm();
    signupForm.setLastName("formLast");
    signupForm.setFirstName("Dave");
    signupForm.setEmail("form@test.com")

    sampleService.saveFrom(signupForm);
}

This test doesn’t actually use mockito because the exception is thrown in the service and not the DAO. If we had special logic handling DAO exceptions then I would use the “thenThrow()” in mockito and test accordingly. This test does however utilize JUnit’s “expected” option telling the test to expect a certain type of exception. This eliminated the need for a try/catch block or fail() statements. If a different or no exception is thrown then the test fails.

Now our class is tested and it’s time to move on. If you are a stickler for code coverage, you would notice that we hit the lines but missed a branch. !StringUtils.isEmpty(firstName) was never specifically tested. Testing this comes down to philosophy. Adding that test may be low value because it exercises the same code. However a test would help protect against a bad && or || situation or someone changing the exception conditions. My take is that in this scenario it takes minimal time to add, is low maintenance and would specifically test code assumptions.

Annotation Method

Now that you have seen the long way, here is a quick setup using annotations. I use the same setup when using Spring MVC Test which can been seen in the controller testing example.


@RunWith(MockitoJUnitRunner.class)
public class SampleServiceIntegrationTest {

    @Mock
    UserDao userDao;

    @InjectMocks
    SampleService sampleService = new SampleServiceImpl();

Here we add the @RunWith(MockitoJUnitRunner.class) annotations. This instructs mockito to process the annotations for Mock & InjectMocks.

@Mock replaces the mock(UserDao.class) declaration in setup. Notice here that @Before is no longer needed.

To make this work I used the empty constructor for SampleService.

Testing Series
This post is one in a series about end to end testing of Spring MVC applications. If you are interested in other levels of application testing then check out the series index here.

2 Comments

  1. ram March 27, 2015
  2. krishna October 15, 2013

Leave a Reply

Your email address will not be published. Required fields are marked *