概述 在本文中,我们将看看如何使用Spring Boot中的框架支持编写测试。 我们将介绍可以单独运行的单元测试以及在执行测试之前引导Spring上下文的集成测试。
工程安装 我们将在本文中使用的应用程序是一个API,它提供了一些员工资源的基本操作。 这是一个典型的分层架构 - API调用从Controller到Service到Persistence层。
Maven 依赖 1 2 3 4 5 6 7 8 9 10 11 12 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > <version > 1.5.3.RELEASE</version > </dependency > <dependency > <groupId > com.h2database</groupId > <artifactId > h2</artifactId > <scope > test</scope > <version > 1.4.194</version > </dependency >
用@DataJpaTest 测试持久层 示例实体
1 2 3 4 5 6 7 8 9 10 11 12 13 @Entity @Table (name = "person" ) public class Employee { @Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; @Size (min = 3 , max = 20 ) private String name; }
持久库
1 2 3 4 5 6 @Repositorypublic interface EmployeeRepository extends JpaRepository <Employee , Long > { public Employee findByName(String name); }
单元测试示便
1 2 3 4 5 6 7 8 9 10 11 12 13 @RunWith (SpringRunner.class)@DataJpaTest public class EmployeeRepositoryTest { @Autowired private TestEntityManager entityManager; @Autowired private EmployeeRepository employeeRepository; }
测试函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void when FindByName_thenReturnEmployee() { Employee alex = new Employee("alex" ) ; entityManager.persist(alex); entityManager.flush() ; Employee found = employeeRepository.findByName(alex .getName () ); assert That(found .getName () ) .isEqualTo(alex .getName () ); }
用@MockBean 测试服务层 示例服务层
1 2 3 4 5 6 7 8 9 10 11 @Service public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeRepository employeeRepository; @Override public Employee getEmployeeByName (String name ) { return employeeRepository.findByName (name); } }
测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RunWith(SpringRunner.class) public class EmployeeServiceImplTest { @TestConfiguration static class EmployeeServiceImplTestContextConfiguration { @Bean public EmployeeService employeeService () { return new EmployeeServiceImpl (); } } @Autowired private EmployeeService employeeService; @MockBean private EmployeeRepository employeeRepository; }
测试函数:
1 2 3 4 5 6 7 8 @Test public void when ValidName_thenEmployeeShouldBeFound() { String name = "alex" ; Employee found = employeeService.getEmployeeByName(name ) ; assert That(found .getName () ) .isEqualTo(name ) ; }
用@WebMvcTest 测试web层 web层示例
1 2 3 4 5 6 7 8 9 10 11 12 @RestController @RequestMapping ("/api" ) public class EmployeeRestController { @Autowired private EmployeeService employeeService; @GetMapping ("/employees" ) public List<Employee> getAllEmployees () { return employeeService .getAllEmployees (); } }
测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 @RunWith (SpringRunner.class)@WebMvcTest (EmployeeRestController.class) public class EmployeeRestControllerTest { @Autowired private MockMvc mvc; @MockBean private EmployeeService service; }
测试函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void givenEmployees_whenGetEmployees_thenReturnJsonArray() throws Exception { Employee alex = new Employee("alex" ) ; List<Employee> allEmployees = Arrays .as List(alex ) ; given(service.getAllEmployees() ).willReturn(allEmployees ) ; mvc.perform(get("/api/employees" ) .contentType(MediaType.APPLICATION_JSON) ) .and Expect(status () .isOk() ) .and Expect(jsonPath ("$" , hasSize (1) )) .and Expect(jsonPath ("$[0].name" , is (alex .getName () ))); }
用@SpringBootTest进行集成测试 tips 1 2 3 @RunWith (SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration (classes = SpringBootSampleApplication.class) @WebAppConfiguration
结论 在本教程中,我们深入介绍了Spring Boot中的测试支持,并展示了如何高效编写单元测试。 本文的完整源代码可以在GitHub 上找到。源代码包含更多的示例和各种测试用例。
参考