I’ve been wanting to enhance the unit tests I have in my application for awhile. I’m using Spring 3 testing facilities, but most of my tests are “integration” tests. I finally carved out a bit of time to enable better unit tests in my application. This is an example of a unit test of a simple service class using Spring 3 annotations. I am using Mockito to mock the dependencies.
First my service class. Like I said, simple. Just two methods and straightforward logic.
package my.app.service;
import java.util.List;
import my.app.dao.SupervisorDAO;
import my.app.model.Supervisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SupervisorService {
@Autowired private SupervisorDAO supervisorDao;
@Transactional(readOnly=true)
public List getSupervisors() {
return supervisorDao.getSupervisors();
}
/**
* Determine if the supervisor is responsible for any users for the
* specified department
* @param dbId The dbId of the supervisor
* @param department The department to look for
* @return true if there are users assigned to the superivsor for the department
*/
public boolean isSupervisorResponsibleForUser(int dbId, String department) {
if (dbId == 0) {
throw new IllegalArgumentException("A dbId is required");
}
if (department == null) {
throw new IllegalArgumentException("department is required");
}
boolean hasUsers = false;
int numAssignedUsers = supervisorDao.getUserCountForSupervisor(dbId, department);
if (numAssignedUsers > 0) {
hasUsers = true;
}
return hasUsers;
}
}
The unit test. I need to mock the dao object to create a repeatable unit test of the service class. Here’s the code:
package my.app.service;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import my.app.dao.SupervisorDAO;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SupervisorServiceUnitTest {
@Mock private SupervisorDAO mockSupervisorDao;
@InjectMocks private SupervisorService supervisorService;
@Before
public void init() {
when(mockSupervisorDao.getUserCountForSupervisor(1, "Department1"))
.thenReturn(2);
when(mockSupervisorDao.getUserCountForSupervisor(1, "Department2"))
.thenReturn(0);
}
@Test
public void testIsSupervisorResponsibleForUserTrue() {
boolean isSupervisor = supervisorService.isSupervisorResponsibleForUser(1, "Department1");
assertTrue(isSupervisor);
}
@Test
public void testIsSupervisorResponsibleForUserFalse() {
boolean isSupervisor = supervisorService.isSupervisorResponsibleForUser(1, "Department2");
assertFalse(isSupervisor);
}
@Test(expected=IllegalArgumentException.class)
public void testIsSupervisorResponsibleRequiredDbId() {
supervisorService.isSupervisorResponsibleForUser(0, "Department3");
}
@Test(expected=IllegalArgumentException.class)
public void testIsSupervisorResponsibleRequiredDivision() {
supervisorService.isSupervisorResponsibleForUser(1, null);
}
}
The key things that I learned along the way:
- Use @RunWith(MockitoJUnitRunner.class) to run this test
- Use the @Mock annotation for the classes that need to be mocked within the class you are testing. Use the @InjectMocks annotation on the class you are testing. The @Mock classes are injected into the @InjectMocks class. I guess this should have been obvious, but it wasn’t to me.
It’s a simple class and a simple unit test, but it’s a start. It gets me over the hump of having the correct jars and knowing how to get a test up and running. I am new to the behavior driven style of Mockito, but this works well for me in this unit test. I think it is clean and easy to read.
Some links that were helpful to me (disclaimer, some of these are for older versions of Mockito)
Version Info:
- Spring 3.0.5
- Mockito 1.9.0