如何对DAO组件进行单元测试

时间:2020-02-23 14:33:11  来源:igfitidea点击:

在本教程中,我们将学习如何为dao创建单元测试。作为准备工作,我们需要了解DAOs的基本知识。

在测试DAO组件时,我们实际上有两种方法。一种是使用mocking框架Mockito,另一种是创建两个可以协同工作的类。

在本教程中,我们将使用Mockito。

**员工Knife **

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", "[email protected]"));
		employees.add(new Employee("Demo2", "[email protected]"));
		employees.add(new Employee("Demo3", "[email protected]"));
		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);
	}
}

如果我们想知道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;
	}
}

getter/employee方法只是一个标准的构造函数。

现在是时候为DAO类创建测试类了。

员工考核

@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));
	}
}

故障

在上一个类中,有一些事情需要分解。

首先,请注意,我们使用的是@MockBean注释,它只是将mock对象添加到应用程序上下文中。这意味着,这将替换任何现有的相同类型的bean。如果没有任何现有的bean,将创建一个新的bean。

然后我们使用@beforeach注释,它将在所有单元测试运行之前执行。因此,方法的名称是 准备,我们正在为单元测试准备“环境”。

在prepare方法中,我们有一些东西。因为SessionFactory是一个函数接口,所以它可以用作lambda表达式的赋值。

我们使用 **莫基托什么时候]方法中的方法。它用于模拟在调用期间给出异常的方法。所以这条线

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

实际上是在说“给我当前会话,如果没有异常,则将会话返回给我”。之后,我们只需将DAO实例分配给一个全新的实例:

employeeDAO = new EmployeeDAO(sessionFactory);

在那之后,我们有了我们的 test purpose方法,名为 should\ureturnNull ifNonExistent(),它的作用就是:返回一个null,如果没有要返回的列表,则返回一个空的ArrayList。但是,在我们的EmployeeDAO实现中,我们永远不会冒着获得 null的风险,因为我们在创建EmployeeDAO()的实例后,就在列表中添加了三个EmployeeDAO()条目:

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

注意方法的 @Test annotation。它指定此方法用于测试目的。我们在 EmployeeDAO类中得到我们重写的“get”方法,如果没有异常,则返回类型为 Queryq,然后返回一个新的空数组列表。

之后,我们使用getAll()方法至少返回3个条目,然后使用结合了 AssertNoteEqualsassertEqualsassertAll()方法。台词:

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

实际上是说检查l(包含从getAll()方法返回的项的列表)是否不是空的,并检查列表的大小是否为0。如果是,返回true,assertEquals将计算为true。