For further reference, please consider the following sections:
Due to Maven's design, elements are inherited from the parent POM to the project POM.
While most of the inheritance is fine, it also inherits unwanted elements like <license>
and <developers>
from the
parent.
To prevent this, the project POM contains empty overrides for these elements.
If you manually switch to a different parent and actually want the inheritance, you need to remove those overrides.
学习使用JUnit 5和Mockito测试框架为 Spring Boot 应用程序的服务层编写单元测试。我们在此演示中使用Spring Boot 3。对于 Spring Boot 应用程序,我们只需要更改 import 语句,一切都会自动运行。
@ExtendWith(MockitoExtension.class)
public class ItemServiceTest {
@Mock
private ItemRepository itemRepository;
@InjectMocks
private ItemService itemService; // 假设 ItemService 使用 ItemRepository
@Test
public void testCreateItem() {
// ...
}
}
spring-boot-starter-test依赖项会间接导入 JUnit 5 和 Mockito。因此我们只需要包含此依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
在这个例子中,我们主要对两个类EmployeeManager
和EmployeeDao
进行单元测试。顾名思义,manager 类代表服务层,而 dao 类与数据库交互。
EmployeeManager
类依赖于EmployeeDao
来从数据库获取数据,这些数据最终返回给控制器类。为了测试EmployeeManager
中的方法,我们可以通过以下两种方式创建一个 JUnit 测试类TestEmployeeManager :
@Mock 注解为所注解的类创建一个模拟实现。
@InjectMocks还创建注解类型的模拟实现并将依赖的模拟注入其中。
在上面的例子中,我们用@InjectMocks
注解了EmployeeManager
类,因此 mockito 将为EmployeeManager
类创建模拟对象,并将EmployeeDao
的模拟依赖项注入其中。
要使用 JUnit 处理 Mockito 注释,我们需要使用MockitoExtention ,它会自动初始化所有带有@Mock
和@InjectMocks
注释的对象。
@ExtendWith(MockitoExtension.class)
public class TestEmployeeManager {
@InjectMocks
EmployeeManager manager;
@Mock
EmployeeDao dao;
//tests
}
如果我们不使用MockitoJUnitRunner类方法,那么我们可以使用静态方法 MockitoAnnotations.openMocks()
。在初始化 junit 测试时,此方法还会初始化模拟对象。
public class ServiceTests {
@InjectMocks
EmployeeService service;
@Mock
EmployeeRepository dao;
@BeforeEach
public void init() {
MockitoAnnotations.openMocks(this);
}
//tests
}
让我们看几个编写 junit 测试的例子,使用 mockito 创建的模拟对象对服务层和DAO 层方法进行单元测试。
一些示例方法可以是*getAllEmployees()*返回EmployeeVO
对象列表、 <em>getEmployeeById(int id)</em>
根据给定的 id 返回员工;以及createEmployee()
添加员工对象并返回void
。
以下类包含服务类方法的测试。它使用*Mockito.when()*方法创建测试存根。
import com.mock.mockito.dao.EmployeeRepository;
import com.mock.mockito.entity.Employee;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class EmployeeServiceTest {
@InjectMocks
EmployeeService service;
@Mock
EmployeeRepository repository;
/**
* 保存对象的方法
*/
@Test
public void testSave(){
Employee employee = new Employee("1", "2");
Employee save = service.save(employee);
assertEquals(save, null);
}
/**
* 测试异常情况
*/
@Test
public void testSaveNull(){
when(service.save(null)).thenThrow(new NullPointerException());
}
/**
* 查询所有的数据
*
* @return list
*/
@Test
public void testFindAllEmployees(){
// 模拟从dao 层查询出所有数据
List<Employee> list = initEmployees();
when(repository.findAll()).thenReturn(list);
// 调用service 层中的findAll() 方法查询数据
List<Employee> all = service.findAll();
// 判断两次查询的数据数量是否一致
assertEquals(list.size(), all.size());
}
/**
* 初始化数据
*
* @return list
*/
private List<Employee> initEmployees() {
List<Employee> list = new ArrayList<>();
Employee empOne = new Employee("John", "John");
Employee empTwo = new Employee("Alex", "kolenchiski");
Employee empThree = new Employee("Steve", "Waugh");
list.add(empOne);
list.add(empTwo);
list.add(empThree);
return list;
}
}
请注意,如果在测试执行期间未调用初始化的模拟,则Mockito会抛出UnsupportedStubbingException 。如果有此类可选的模拟行为,则使用Mockito.lenient() 如下所示:
Mockito.lenient().when(dao .isEmployeeDeleted()).thenReturn(Boolean.False);
package com.mock.mockito.service;
import com.mock.mockito.dao.EmployeeRepository;
import com.mock.mockito.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmployeeService {
@Autowired
EmployeeRepository employeeRepository;
public Employee save(Employee employee) {
//...
if (employee != null){
Employee save = employeeRepository.save(employee);
return save;
}else {
throw new NullPointerException("the employee is not allowed be null");
}
}
public List<Employee> findAll() {
//...
List<Employee> all = (List<Employee>) employeeRepository.findAll();
return all;
}
public void deleteById(Integer id) {
//...
if (id != null){
employeeRepository.deleteById(id);
}else {
throw new NullPointerException("the id is not allowed be null");
}
}
public void deleteAll() {
//...
employeeRepository.deleteAll();
}
}
实体类:
package com.mock.mockito.entity;
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
dao层:
package com.mock.mockito.dao;
import com.mock.mockito.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
}
本 mockito 教程教我们使用 JUnit 和 Mockito 对 spring boot 应用程序中的服务层进行单元测试。我们学习了如何设置测试类和编写 JUnit 测试。我们还学习了*@Mock和@InjectMocks*注释之间的区别。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。