原文: https://howtodoinjava.com/spring-boot2/testing/spring-boot-mockito-junit-example/

学习使用 JUnitMockito 测试框架为 Spring 应用的服务层编写单元测试。 本教程演示 SpringBoot 测试服务层示例

1. Maven 依赖

spring-boot-starter-test依赖项包括创建和执行测试所需的所有依赖项。

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-test</artifactId>
  4. </dependency>

如果不使用 spring boot,则包括以下依赖项。

  1. <dependency>
  2. <groupId>junit</groupId>
  3. <artifactId>junit</artifactId>
  4. <version>4.12</version>
  5. <scope>test</scope>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.mockito</groupId>
  9. <artifactId>mockito-core</artifactId>
  10. <version>2.15.0</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.mockito</groupId>
  14. <artifactId>mockito-inline</artifactId>
  15. <version>2.15.0</version>
  16. </dependency>

2. 起步

在此示例中,我们主要对两个类EmployeeManagerEmployeeDao进行单元测试。 顾名思义,管理器类代表服务层,而 dao 类正在与数据库进行交互。

EmployeeManager类依赖于EmployeeDao和委托方法调用来获取 pis 最终返回到控制器类的数据。

为了测试EmployeeManager中的方法,我们可以通过以下两种方式创建 JUnit 测试类 TestEmployeeManager

2.1 MockitoJUnitRunner

MockitoJUnitRunner类自动初始化所有带有@Mock@InjectMock注解的对象。

  1. @RunWith(MockitoJUnitRunner.class)
  2. public class TestEmployeeManager {
  3. @InjectMock
  4. EmployeeManager manager;
  5. @Mock
  6. EmployeeDao dao;
  7. //tests
  8. }

2.2 MockitoAnnotations.initMock()方法

如果我们不使用MockitoJUnitRunner类方法,则可以使用静态方法MockitoAnnotations.initMock()。 在初始化 junit 测试时,该方法还会初始化模拟对象。

  1. public class TestEmployeeManager {
  2. @InjectMock
  3. EmployeeManager manager;
  4. @Mock
  5. EmployeeDao dao;
  6. @Before
  7. public void init() {
  8. MockitoAnnotations.initMock(this);
  9. }
  10. //tests
  11. }

2.3 @Mock vs @InjectMock

  • @Mock 注解会为其注解的类创建一个模拟实现。
  • @InjectMock 还将创建模拟实现,另外将标有注解@Mock的从属模拟注入其中。

在上面的示例中,我们用@InjectMock注解了EmployeeManager类,因此模仿者将为EmployeeManager类创建模仿对象,并将EmployeeDao的模仿依赖项注入其中。

3. 使用 Mockito 进行 JUnit 测试

让我们看几个例子,这些例子编写了 junit 测试,以使用通过嘲讽创建的模拟对象对服务层方法进行单元测试。

很少有示例方法是getAllEmployees(),该方法将返回EmployeeVO对象的列表,getEmployeeById(int id)以给定 id 返回雇员。 和createEmployee()将添加一个雇员对象并返回void

3.1 服务层测试

  1. package com.howtodoinjava.demo;
  2. import static org.junit.Assert.assertEquals;
  3. import static org.mockito.Mockito.times;
  4. import static org.mockito.Mockito.verify;
  5. import static org.mockito.Mockito.when;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import org.junit.runner.RunWith;
  11. import org.mockito.InjectMock;
  12. import org.mockito.Mock;
  13. import org.mockito.MockitoAnnotations;
  14. import org.mockito.junit.MockitoJUnitRunner;
  15. import com.howtodoinjava.demo.dao.EmployeeDao;
  16. import com.howtodoinjava.demo.model.EmployeeVO;
  17. import com.howtodoinjava.demo.service.EmployeeManager;
  18. public class TestEmployeeManager {
  19. @InjectMock
  20. EmployeeManager manager;
  21. @Mock
  22. EmployeeDao dao;
  23. @Before
  24. public void init() {
  25. MockitoAnnotations.initMock(this);
  26. }
  27. @Test
  28. public void getAllEmployeesTest()
  29. {
  30. List<EmployeeVO> list = new ArrayList<EmployeeVO>();
  31. EmployeeVO empOne = new EmployeeVO(1, "John", "John", "howtodoinjava@gmail.com");
  32. EmployeeVO empTwo = new EmployeeVO(2, "Alex", "kolenchiski", "alexk@yahoo.com");
  33. EmployeeVO empThree = new EmployeeVO(3, "Steve", "Waugh", "swaugh@gmail.com");
  34. list.add(empOne);
  35. list.add(empTwo);
  36. list.add(empThree);
  37. when(dao.getEmployeeList()).thenReturn(list);
  38. //test
  39. List<EmployeeVO> empList = manager.getEmployeeList();
  40. assertEquals(3, empList.size());
  41. verify(dao, times(1)).getEmployeeList();
  42. }
  43. @Test
  44. public void getEmployeeByIdTest()
  45. {
  46. when(dao.getEmployeeById(1)).thenReturn(new EmployeeVO(1,"Lokesh","Gupta","user@email.com"));
  47. EmployeeVO emp = manager.getEmployeeById(1);
  48. assertEquals("Lokesh", emp.getFirstName());
  49. assertEquals("Gupta", emp.getLastName());
  50. assertEquals("user@email.com", emp.getEmail());
  51. }
  52. @Test
  53. public void createEmployeeTest()
  54. {
  55. EmployeeVO emp = new EmployeeVO(1,"Lokesh","Gupta","user@email.com");
  56. manager.addEmployee(emp);
  57. verify(dao, times(1)).addEmployee(emp);
  58. }
  59. }

单元测试结果将是这样。

Spring Boot,Mockito 和 Junit – 单元测试服务层 - 图1

Spring boot mockito junit 示例

3.2 服务层类

  1. import java.util.List;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Service;
  4. import com.howtodoinjava.demo.dao.EmployeeDao;
  5. import com.howtodoinjava.demo.model.EmployeeVO;
  6. @Service
  7. public class EmployeeManager
  8. {
  9. @Autowired
  10. EmployeeDao dao;
  11. public List<EmployeeVO> getEmployeeList() {
  12. return dao.getEmployeeList();
  13. }
  14. public EmployeeVO getEmployeeById(int id) {
  15. return dao.getEmployeeById(id);
  16. }
  17. public void addEmployee(EmployeeVO employee) {
  18. dao.addEmployee(employee);
  19. }
  20. }

3.3 DAO 层类

  1. package com.howtodoinjava.demo.dao;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import org.springframework.stereotype.Repository;
  7. import com.howtodoinjava.demo.model.EmployeeVO;
  8. @Repository
  9. public class EmployeeDao {
  10. private Map<Integer, EmployeeVO> DB = new HashMap<>();
  11. public List<EmployeeVO> getEmployeeList()
  12. {
  13. List<EmployeeVO> list = new ArrayList<>();
  14. if(list.isEmpty()) {
  15. list.addAll(DB.values());
  16. }
  17. return list;
  18. }
  19. public EmployeeVO getEmployeeById(int id) {
  20. return DB.get(id);
  21. }
  22. public void addEmployee(EmployeeVO employee) {
  23. employee.setEmployeeId(DB.keySet().size() + 1);
  24. DB.put(employee.getEmployeeId(), employee);
  25. }
  26. public void updateEmployee(EmployeeVO employee) {
  27. DB.put(employee.getEmployeeId(), employee);
  28. }
  29. public void deleteEmployee(int id) {
  30. DB.remove(id);
  31. }
  32. }

4. Spring Boot Mockito 示例 – 总结

在此 mockito 教程中,我们学习了使用 JUnit 和 Mockito 对 Spring Boot 应用中的服务层进行单元测试。 我们学习了如何设置测试类并编写 JUnit 测试。

我们还了解了@Mock@InjectMock注解之间的区别

学习愉快!