Spring Boot中的测试

文章目录

Spring Boot中的测试

简介

本篇文章我们将会探讨一下怎么在SpringBoot使用测试,Spring Boot有专门的spring-boot-starter-test,通过使用它可以很方便的在Spring Boot进行测试。

本文将从repository,service, controller,app四个层级来详细描述测试案例。

添加maven依赖

1<dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-test</artifactId> 4 <scope>test</scope> 5</dependency> 6<dependency> 7 <groupId>com.h2database</groupId> 8 <artifactId>h2</artifactId> 9 <scope>test</scope> 10</dependency>

我们添加spring-boot-starter-test和com.h2database总共两个依赖。H2数据库主要是为了测试方便。

Repository测试

本例中,我们使用JPA,首先创建Entity和Repository:

1@Entity 2@Table(name = "person") 3public class Employee { 4 5 @Id 6 @GeneratedValue(strategy = GenerationType.AUTO) 7 private Long id; 8 9 @Size(min = 3, max = 20) 10 private String name; 11 12 // standard getters and setters, constructors 13} 14 15@Repository 16public interface EmployeeRepository extends JpaRepository<Employee, Long> { 17 18 public Employee findByName(String name); 19 20}

测试JPA,我们需要使用@DataJpaTest:

1@RunWith(SpringRunner.class) 2@DataJpaTest 3public class EmployeeRepositoryIntegrationTest { 4 5 @Autowired 6 private TestEntityManager entityManager; 7 8 @Autowired 9 private EmployeeRepository employeeRepository; 10 11 // write test cases here 12 13}

@RunWith(SpringRunner.class) 是Junit和Spring Boot test联系的桥梁。

@DataJpaTest为persistence layer的测试提供了如下标准配置:

  • 配置H2作为内存数据库
  • 配置Hibernate, Spring Data, 和 DataSource
  • 实现@EntityScan
  • 开启SQL logging

下面是我们的测试代码:

1@Test 2public void whenFindByName_thenReturnEmployee() { 3 // given 4 Employee alex = new Employee("alex"); 5 entityManager.persist(alex); 6 entityManager.flush(); 7 8 // when 9 Employee found = employeeRepository.findByName(alex.getName()); 10 11 // then 12 assertThat(found.getName()) 13 .isEqualTo(alex.getName()); 14}

在测试中,我们使用了TestEntityManager。 TestEntityManager提供了一些通用的对Entity操作的方法。上面的例子中我们使用TestEntityManager向Employee插入了一条数据。

Service测试

在实际的应用程序中,Service通常要使用到Repository。但是在测试中我们可以Mock一个Repository,而不用使用真实的Repository。

先看一下Service:

1@Service 2public class EmployeeServiceImpl implements EmployeeService { 3 4 @Autowired 5 private EmployeeRepository employeeRepository; 6 7 @Override 8 public Employee getEmployeeByName(String name) { 9 return employeeRepository.findByName(name); 10 } 11}

我们再看一下怎么Mock Repository。

1@RunWith(SpringRunner.class) 2public class EmployeeServiceImplIntegrationTest { 3 4 @TestConfiguration 5 static class EmployeeServiceImplTestContextConfiguration { 6 7 @Bean 8 public EmployeeService employeeService() { 9 return new EmployeeServiceImpl(); 10 } 11 } 12 13 @Autowired 14 private EmployeeService employeeService; 15 16 @MockBean 17 private EmployeeRepository employeeRepository; 18 19 // write test cases here 20}

看下上面的例子,我们首先使用了@TestConfiguration专门用在测试中的配置信息,在@TestConfiguration中,我们实例化了一个EmployeeService Bean,然后在EmployeeServiceImplIntegrationTest自动注入。

我们还是用了@MockBean,用来Mock一个EmployeeRepository。

我们看下Mock的实现:

1@Before 2 public void setUp() { 3 Employee alex = new Employee("alex"); 4 5 Mockito.when(employeeRepository.findByName(alex.getName())) 6 .thenReturn(alex); 7 } 8 9 @Test 10 public void whenValidName_thenEmployeeShouldBeFound() { 11 String name = "alex"; 12 Employee found = employeeService.getEmployeeByName(name); 13 14 assertThat(found.getName()) 15 .isEqualTo(name); 16 }

上面的代码中,我们使用Mockito来Mock要返回的数据,然后在接下来的测试中使用。

测试Controller

和测试Service一样,Controller使用到了Service:

1@RestController 2@RequestMapping("/api") 3public class EmployeeRestController { 4 5 @Autowired 6 private EmployeeService employeeService; 7 8 @GetMapping("/employees") 9 public List<Employee> getAllEmployees() { 10 return employeeService.getAllEmployees(); 11 } 12}

但是在测试的时候,我们并不需要使用真实的Service,我们需要Mock它 。

1@RunWith(SpringRunner.class) 2@WebMvcTest(EmployeeRestController.class) 3public class EmployeeControllerIntegrationTest { 4 5 @Autowired 6 private MockMvc mvc; 7 8 @MockBean 9 private EmployeeService service; 10 11 // write test cases here

为了测试Controller,我们需要使用到@WebMvcTest,他会为Spring MVC 自动配置所需的组件。

通常情况下@WebMvcTest 会和@MockBean一起使用来提供Mock的具体实现。

@WebMvcTest也提供了自动配置的MockMvc,它为测试MVC Controller提供了更加简单的方式,而不需要启动完整的HTTP server。

1@Test 2public void givenEmployees_whenGetEmployees_thenReturnJsonArray() 3 throws Exception { 4 5 Employee alex = new Employee("alex"); 6 7 List<Employee> allEmployees = Arrays.asList(alex); 8 9 given(service.getAllEmployees()).willReturn(allEmployees); 10 11 mvc.perform(get("/api/employees") 12 .contentType(MediaType.APPLICATION_JSON)) 13 .andExpect(status().isOk()) 14 .andExpect(jsonPath("$", hasSize(1))) 15 .andExpect(jsonPath("$[0].name", is(alex.getName()))); 16}

given(service.getAllEmployees()).willReturn(allEmployees); 这一行代码提供了mock的输出。方面后面的测试使用。

@SpringBootTest的集成测试

上面我们讲的都是单元测试,这一节我们讲一下集成测试。

1@RunWith(SpringRunner.class) 2@SpringBootTest( 3 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, 4 classes = TestApplication.class) 5@AutoConfigureMockMvc 6@TestPropertySource( 7 locations = "classpath:application-integrationtest.properties") 8public class EmployeeAppIntegrationTest { 9 10 @Autowired 11 private MockMvc mvc; 12 13 @Autowired 14 private EmployeeRepository repository; 15}

集成测试需要使用@SpringBootTest,在@SpringBootTest中可以配置webEnvironment,同时如果我们需要自定义测试属性文件可以使用@TestPropertySource。

下面是具体的测试代码:

1@After 2 public void resetDb() { 3 repository.deleteAll(); 4 } 5 6 @Test 7 public void givenEmployees_whenGetEmployees_thenStatus200() throws Exception { 8 createTestEmployee("bob"); 9 createTestEmployee("alex"); 10 11 // @formatter:off 12 mvc.perform(get("/api/employees").contentType(MediaType.APPLICATION_JSON)) 13 .andDo(print()) 14 .andExpect(status().isOk()) 15 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) 16 .andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2)))) 17 .andExpect(jsonPath("$[0].name", is("bob"))) 18 .andExpect(jsonPath("$[1].name", is("alex"))); 19 // @formatter:on 20 } 21 22 // 23 24 private void createTestEmployee(String name) { 25 Employee emp = new Employee(name); 26 repository.saveAndFlush(emp); 27 }

本文的例子可以参考https://github.com/ddean2009/learn-springboot2/tree/master/springboot-test

更多教程请参考 flydean的博客

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593

Spring Boot的TestRestTemplate使用

文章目录添加maven依赖(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fsuperfjj%2Farticle%2Fdetails%2F104219960%23maven_7)TestRestTemplateVSRes

Spring Boot中的Properties

文章目录简介(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fsuperfjj%2Farticle%2Fdetails%2F104243859%23_3)使用注解注册一个Properties文件(https://www.o