Mockito Tutorial

Mockito is a testing framework and widely used now. Lets see how to use this in this tutorial.

I am going to use Maven + Java 8 + Mockito 2.0.2-beta version for this example.

Assume that we have a class called User Service which does save, get, remove and update operation on DB. So UserService class contains an instance of UserDao class which does all the CRUD operations. Here are those classes.

UserService.java


package com;

import java.util.UUID;

public class UserService {

    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User get(String id) {
        return userDao.get(id);
    }

    public String save(String firstName, String lastName, int age) throws Exception {
        User user = new User();
        user.setAge(age);
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setId(UUID.randomUUID().toString());
        return userDao.save(user);
    }

    public String remove(String id) throws Exception {
        return userDao.remove(id);
    }

    public String update(String id, String firstName, String lastName, int age) throws Exception {
        User user = new User();
        user.setAge(age);
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setId(id);
        return userDao.update(user);
    }
}

UserDao.java



package com;

public interface UserDao {
    public User get(String id);
    public String save(User user) throws Exception;
    public String remove(String id) throws Exception;
    public String update(User user) throws Exception;
}


UserDaoImpl.java
Its a dummy class only and actual implementation may be different


package com;

public class UserDaoImpl implements UserDao {

    @Override
    public User get(String id) {
        //Dummy implementation
        return null;
    }

    @Override
    public String save(User user) throws Exception {
        return "id";
    }

    @Override
    public String remove(String id) throws Exception {
       return id;
    }

    @Override
    public String update(User user) throws Exception {
        return "id";
    }
}


Now we want to mock the UserDao class and write the unit test cases for the UserService class. Here is my Junit test case


import com.User;
import com.UserDao;
import com.UserService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.times;

public class UserServiceTest {

    UserDao userDao;

    User mockUser;

    UserService userService;

    @Before
    public void setUp() {
        userDao = Mockito.mock(UserDao.class);
        userService = new UserService(userDao);
        mockUser = new User();
        mockUser.setId(UUID.randomUUID().toString());
        mockUser.setFirstName("test");
        mockUser.setLastName("test");
        mockUser.setAge(40);
    }

    @Test
    public void testSave() throws Exception {
        //Using argument captor to test the values passed to the UserDao.save method
        ArgumentCaptor userArgumentCaptor = ArgumentCaptor.forClass(User.class);
        userService.save("bala", "samy", 35);
        Mockito.verify(userDao).save(userArgumentCaptor.capture());
        //Test the method called once
        Mockito.verify(userDao, times(1)).save(any());
        User storedUser = userArgumentCaptor.getValue();
        assertEquals("bala", storedUser.getFirstName());
        assertEquals("samy", storedUser.getLastName());
        assertEquals(35, storedUser.getAge());

    }

    @Test
    public void testGetUsingSpy() throws Exception {
        UserService userService = new UserService(userDao);
        UserService spy = Mockito.spy(userService);
        Mockito.when(spy.get(mockUser.getId())).thenReturn(mockUser);
        assertEquals(mockUser, spy.get(mockUser.getId()));
    }

    @Test
    public void testGetWithMock() throws Exception {
        Mockito.when(userDao.get(mockUser.getId())).thenReturn(mockUser);
        assertEquals(mockUser, userService.get(mockUser.getId()));
    }

    @Test
    public void testSaveWithMock() throws Exception {
        Mockito.when(userDao.save(any())).thenReturn(mockUser.getId());
        String value = userService.save(mockUser.getFirstName(), mockUser.getLastName(), mockUser.getAge());
        assertEquals(mockUser.getId(), value);
    }

    @Test
    public void testRemoveWithMock() throws Exception {
        Mockito.when(userDao.remove(any())).thenReturn(mockUser.getId());
        assertEquals(mockUser.getId(),userService.remove(mockUser.getId()));
    }

}


Argument Captor:

In the testSave method, I have used Argument Captor to capture the arguments that are getting passed to the UserDao.save method. Here we are passing the User Object to that method. So if we want to verify the async call or test the arguments to any class, then we could use Argument Captor.

In all the remaining test methods, I have mocked the methods of UserDao class.

Refer the code @https://github.com/dkbalachandar/mockitoExample