如何对DAO组件进行单元测试
在本教程中,我们将学习如何为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”方法,如果没有异常,则返回类型为 Query的 q,然后返回一个新的空数组列表。
之后,我们使用getAll()方法至少返回3个条目,然后使用结合了 AssertNoteEquals和 assertEquals的 assertAll()方法。台词:
assertAll("Employees", () -> assertNotEquals(l, null), () -> assertEquals(l.size(), 0));
实际上是说检查l(包含从getAll()方法返回的项的列表)是否不是空的,并检查列表的大小是否为0。如果是,返回true,assertEquals将计算为true。