🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 如何对 DAO 组件进行单元测试 > 原文: [https://javatutorial.net/how-to-unit-test-dao-components](https://javatutorial.net/how-to-unit-test-dao-components) 在本教程中,您将学习如何为 DAO 创建单元测试。 前提条件是,您需要具备 DAO 的基本知识。 ![spring-featured-image](https://img.kancloud.cn/64/23/64231db4bf6e880066d0d4c2e31ac166_780x330.jpg) 在测试 DAO 组件时,我们确实有两种方法。一种是使用模拟框架[`Mockito`](https://site.mockito.org/) ,另一种是创建两个可以协同工作的类。 在本教程中,我们将使用`Mockito`。 `EmployeeDAO` ```java 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); } } ``` 如果您想知道`Employee`类的外观,则为: `Employee.java` ```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; } } ``` 雇员类只是一个标准的构造器/获取器/设置器方法。 现在是时候为 DAO 类创建测试类了。 `EmployeeDAOTest` ```java @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 注解只是将模拟对象添加到应用程序上下文中。 这意味着它将替换任何现有的相同类型的 bean。 如果没有现有的 bean,将创建一个新的 bean。 然后,我们使用`@BeforeEach`注解,该注解将在所有单元测试运行之前执行。 因此,该方法的名称为`prepare`,我们正在为单元测试准备“环境”。 在`prepare`方法中,我们有两件事。 由于[`SessionFactory`](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/remote/session/SessionFactory.html)是一个功能接口,因此可以将其用作 lambda 表达式的分配。 我们在`prepare()`方法中使用`Mockito.when`方法。 它用于在调用过程中给出异常的模拟方法。 所以线 ```java Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session); ``` 确实是在说“让我获得当前会话,如果没有异常,请给我返回该会话”。 然后,我们只需将 DAO 实例分配给一个全新的实例: ```java employeeDAO = new EmployeeDAO(sessionFactory); ``` 之后,我们就有了**测试目标**方法,称为`should_returnNull_ifNonExistent()`,它的名称如实:返回`null`,如果没有则返回空的`ArrayList`要返回的列表。 但是在`EmployeeDAO`实现中,我们永远不会冒**为空**的风险,因为一旦创建`EmployeeDAO()`实例,我们便在列表中添加了三个`Employee`条目: ```java 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; } ``` 注意方法的**`@Test`注解**。 这指定此方法用于测试目的。 我们在`EmployeeDAO`类中获得了被我们覆盖的`get`方法,如果没有异常,则返回`q`类型的查询。 然后我们简单地返回一个新的空数组列表。 之后,我们使用`getAll()`方法至少应返回 3 个条目,然后使用`assertAll()`方法,该方法结合了`assertNotEquals`和`assertEquals`。 这些行: ```java assertAll("Employees", () -> assertNotEquals(l, null), () -> assertEquals(l.size(), 0)); ``` 确实是在说检查`l`(包含从`getAll()`方法返回的条目的列表)是否为空,并检查列表的大小是否为 0。如果是,则返回`true`,`assertEquals`的评估结果为`true`。