How to unit test DAO components

In this tutorial you are going to learn how to create unit tests for DAOs. As a prerequisite, you fundamental knowledge of DAOs is expected.

spring-featured-image

When it  comes to testing DAO components, we really have 2 approaches. One is to use the mocking framework Mockito and the other is to create a couple of classes that work together.

In this tutorial, we will be using Mockito.

EmployeeDAO

public class EmployeeDAO implements Dao<Employee> {
	// will act as a "mini-database"
	private List<Employee> employees = new ArrayList<>();
	private SessionFactory sessFactory;
	// Constructor
	public EmployeeDAO(SessionFactory s) {
		// Populate our list of employees with 3 Demos
		employees.add(new Employee("Demo1", "Demo1@example.com"));
		employees.add(new Employee("Demo2", "Demo2@example.com"));
		employees.add(new Employee("Demo3", "Demo3@example.com"));
		sessFactory = s;
	}
	
	// Overriding the Dao interface methods
	@Override
	public Employee get(long id) {
		return employees.get((int) id));
	}
	
	@Override 
	public List<Employee> getAll() {
		return employees;
	}
	
	@Override
	public void save(Employee emp) {
		employees.add(emp);
	}
	
	@Override
	public void update(Employee employee, String[] params) {
		// Check for validity
		if (params[0].length() != 0|| params[1].length() != 0) {
			// Initialize the employee
			employee.setName(params[0]);
			employee.setEmail(params[1]);
			
			// Add the Initialized employee to the list of employees (a.k.a. DB)
			employees.add(employee);
		}
	}
	
	@Override
	public void delete(Employee employee) {
		employees.remove(employee);
	}
}

If you are wondering how the Employee class looks like, here it is:

Employee.java

public class Employee {
	//members
	private String name;
	private String email;
	
	// constructor
	Employee(String n, String e) {
		name = n;
		email = e;
	}
	
	// setter methods
	public void setName(String n) {
		name = n;
	}
	
	public void setEmail(String e) {
		email = e;
	}
	
	// getter methods
	public String getName() {
		return name;
	}
	
	public String getEmail() {
		return email;
	}
}

The employee class is just a standard constructor/getter/setter methods.

Now it is time to create the test class for the DAO class.

EmployeeDAOTest

@ExtendWith(SpringExtension.class)
@Tag("DAO")
public class EmployeeDAOTest {
	@MockBean
	private SessionFactory sessionFactory;
	
	@MockBean
	private Session session;
	
	private EmployeeDAO employeeDAO;
	
	@BeforeEach
	public void prepare() throws Exception {
		Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session);
		employeeDAO = new EmployeeDAO(sessionFactory);
	}
	
	@Test
	public void should_returnNull_ifNonExistent() {
		Query q = Mockito.mock(Query.class);
		Mockito.when(session.getNamedQuery("get")).thenReturn(q);
		Mockito.when(q.getResultList()).thenReturn(new ArrayList());
		
		List l = employeeDAO.getAll();
		assertAll("Employees", 
		() -> assertNotEquals(l, null),
		() -> assertEquals(l.size(), 0));
	}
}




Breakdown

There are a couple of things to break down in the preceding class.

First, note that we are using the @MockBean annotation which simply put adds mock objects to the application context. Meaning, this will replace any existing bean of the same type. In case there haven’t been any existing beans, a new one will be created.

Then we use the @BeforeEach annotation which will get executed before all the unit tests run. Hence the name of the method, prepare, we are preparing the “environment” for the unit tests.

Within the prepare method, we have a couple of things. Since SessionFactory is a functional interface, it can be used as the assignment for a lambda expression.

We use the Mockito.when method in the prepare() method. It is used for mocking methods which given an exception during a call. So the line

Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session);

really is saying “get me the current session and if there are no exception, return me the session”. And after that, we simply assign the DAO instance to a brand new one:

employeeDAO = new EmployeeDAO(sessionFactory);

After that, we have our very test purpose method, called should_returnNull_ifNonExistent() and does just what the name of it says: returns a null, or an empty ArrayList if there isn’t a list to return. In our EmployeeDAO implementation though, we will never run the risk of getting null as we add three Employee entries  in the List as soon as we create an instance of EmployeeDAO():

public EmployeeDAO(SessionFactory s) {		
   // Populate our list of employees with 3 Demos		
   employees.add(new Employee("Demo1", "Demo1@example.com"));		
   employees.add(new Employee("Demo2", "Demo2@example.com"));		
   employees.add(new Employee("Demo3", "Demo3@example.com"));		
   sessFactory = s;	
}

Note the @Test annotation of the method. This specifies that this method is for testing purposes. We get the “get” method overriden by us in the EmployeeDAO class and if there are not exceptions, thenReturn the q which is of type Query. Then we get simply return a new empty array list.

After that, we use the getAll() method that should give us back 3 entries at least and then we use the assertAll() method which combines assertNotEquals and assertEquals. The lines:

assertAll("Employees", 
		() -> assertNotEquals(l, null),
		() -> assertEquals(l.size(), 0));

are really saying check whether l (the list that contains the entries that have been returned from the getAll() method) is not empty and check if the size of the list is 0. If it is, return true, assertEquals would evaluate to true.

Leave a Reply

avatar