原文: https://javatutorial.net/how-to-unit-test-dao-components
在本教程中,您将学习如何为 DAO 创建单元测试。 前提条件是,您需要具备 DAO 的基本知识。

在测试 DAO 组件时,我们确实有两种方法。一种是使用模拟框架Mockito ,另一种是创建两个可以协同工作的类。
在本教程中,我们将使用Mockito。
EmployeeDAO
public class EmployeeDAO implements Dao<Employee> {// will act as a "mini-database"private List<Employee> employees = new ArrayList<>();private SessionFactory sessFactory;// Constructorpublic EmployeeDAO(SessionFactory s) {// Populate our list of employees with 3 Demosemployees.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@Overridepublic Employee get(long id) {return employees.get((int) id));}@Overridepublic List<Employee> getAll() {return employees;}@Overridepublic void save(Employee emp) {employees.add(emp);}@Overridepublic void update(Employee employee, String[] params) {// Check for validityif (params[0].length() != 0|| params[1].length() != 0) {// Initialize the employeeemployee.setName(params[0]);employee.setEmail(params[1]);// Add the Initialized employee to the list of employees (a.k.a. DB)employees.add(employee);}}@Overridepublic void delete(Employee employee) {employees.remove(employee);}}
如果您想知道Employee类的外观,则为:
Employee.java
public class Employee {//membersprivate String name;private String email;// constructorEmployee(String n, String e) {name = n;email = e;}// setter methodspublic void setName(String n) {name = n;}public void setEmail(String e) {email = e;}// getter methodspublic String getName() {return name;}public String getEmail() {return email;}}
雇员类只是一个标准的构造器/获取器/设置器方法。
现在是时候为 DAO 类创建测试类了。
EmployeeDAOTest
@ExtendWith(SpringExtension.class)@Tag("DAO")public class EmployeeDAOTest {@MockBeanprivate SessionFactory sessionFactory;@MockBeanprivate Session session;private EmployeeDAO employeeDAO;@BeforeEachpublic void prepare() throws Exception {Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session);employeeDAO = new EmployeeDAO(sessionFactory);}@Testpublic 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 注解只是将模拟对象添加到应用程序上下文中。 这意味着它将替换任何现有的相同类型的 bean。 如果没有现有的 bean,将创建一个新的 bean。
然后,我们使用@BeforeEach注解,该注解将在所有单元测试运行之前执行。 因此,该方法的名称为prepare,我们正在为单元测试准备“环境”。
在prepare方法中,我们有两件事。 由于SessionFactory是一个功能接口,因此可以将其用作 lambda 表达式的分配。
我们在prepare()方法中使用Mockito.when方法。 它用于在调用过程中给出异常的模拟方法。 所以线
Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session);
确实是在说“让我获得当前会话,如果没有异常,请给我返回该会话”。 然后,我们只需将 DAO 实例分配给一个全新的实例:
employeeDAO = new EmployeeDAO(sessionFactory);
之后,我们就有了测试目标方法,称为should_returnNull_ifNonExistent(),它的名称如实:返回null,如果没有则返回空的ArrayList要返回的列表。 但是在EmployeeDAO实现中,我们永远不会冒为空的风险,因为一旦创建EmployeeDAO()实例,我们便在列表中添加了三个Employee条目:
public EmployeeDAO(SessionFactory s) {// Populate our list of employees with 3 Demosemployees.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;}
注意方法的@Test注解。 这指定此方法用于测试目的。 我们在EmployeeDAO类中获得了被我们覆盖的get方法,如果没有异常,则返回q类型的查询。 然后我们简单地返回一个新的空数组列表。
之后,我们使用getAll()方法至少应返回 3 个条目,然后使用assertAll()方法,该方法结合了assertNotEquals和assertEquals。 这些行:
assertAll("Employees",() -> assertNotEquals(l, null),() -> assertEquals(l.size(), 0));
确实是在说检查l(包含从getAll()方法返回的条目的列表)是否为空,并检查列表的大小是否为 0。如果是,则返回true,assertEquals的评估结果为true。
