javascript
Spring Boot中的测试
文章目錄
- 簡介
- 添加maven依賴
- Repository測試
- Service測試
- 測試Controller
- @SpringBootTest的集成測試
Spring Boot中的測試
簡介
本篇文章我們將會探討一下怎么在SpringBoot使用測試,Spring Boot有專門的spring-boot-starter-test,通過使用它可以很方便的在Spring Boot進行測試。
本文將從repository,service, controller,app四個層級來詳細描述測試案例。
添加maven依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope> </dependency> <dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>test</scope> </dependency>我們添加spring-boot-starter-test和com.h2database總共兩個依賴。H2數據庫主要是為了測試方便。
Repository測試
本例中,我們使用JPA,首先創建Entity和Repository:
@Entity @Table(name = "person") public class Employee {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Size(min = 3, max = 20)private String name;// standard getters and setters, constructors } @Repository public interface EmployeeRepository extends JpaRepository<Employee, Long> {public Employee findByName(String name);}測試JPA,我們需要使用@DataJpaTest:
@RunWith(SpringRunner.class) @DataJpaTest public class EmployeeRepositoryIntegrationTest {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate EmployeeRepository employeeRepository;// write test cases here}@RunWith(SpringRunner.class) 是Junit和Spring Boot test聯系的橋梁。
@DataJpaTest為persistence layer的測試提供了如下標準配置:
- 配置H2作為內存數據庫
- 配置Hibernate, Spring Data, 和 DataSource
- 實現@EntityScan
- 開啟SQL logging
下面是我們的測試代碼:
@Test public void whenFindByName_thenReturnEmployee() {// givenEmployee alex = new Employee("alex");entityManager.persist(alex);entityManager.flush();// whenEmployee found = employeeRepository.findByName(alex.getName());// thenassertThat(found.getName()).isEqualTo(alex.getName()); }在測試中,我們使用了TestEntityManager。 TestEntityManager提供了一些通用的對Entity操作的方法。上面的例子中我們使用TestEntityManager向Employee插入了一條數據。
Service測試
在實際的應用程序中,Service通常要使用到Repository。但是在測試中我們可以Mock一個Repository,而不用使用真實的Repository。
先看一下Service:
@Service public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeRepository employeeRepository;@Overridepublic Employee getEmployeeByName(String name) {return employeeRepository.findByName(name);} }我們再看一下怎么Mock Repository。
@RunWith(SpringRunner.class) public class EmployeeServiceImplIntegrationTest {@TestConfigurationstatic class EmployeeServiceImplTestContextConfiguration {@Beanpublic EmployeeService employeeService() {return new EmployeeServiceImpl();}}@Autowiredprivate EmployeeService employeeService;@MockBeanprivate EmployeeRepository employeeRepository;// write test cases here }看下上面的例子,我們首先使用了@TestConfiguration專門用在測試中的配置信息,在@TestConfiguration中,我們實例化了一個EmployeeService Bean,然后在EmployeeServiceImplIntegrationTest自動注入。
我們還是用了@MockBean,用來Mock一個EmployeeRepository。
我們看下Mock的實現:
@Beforepublic void setUp() {Employee alex = new Employee("alex");Mockito.when(employeeRepository.findByName(alex.getName())).thenReturn(alex);}@Testpublic void whenValidName_thenEmployeeShouldBeFound() {String name = "alex";Employee found = employeeService.getEmployeeByName(name);assertThat(found.getName()).isEqualTo(name);}上面的代碼中,我們使用Mockito來Mock要返回的數據,然后在接下來的測試中使用。
測試Controller
和測試Service一樣,Controller使用到了Service:
@RestController @RequestMapping("/api") public class EmployeeRestController {@Autowiredprivate EmployeeService employeeService;@GetMapping("/employees")public List<Employee> getAllEmployees() {return employeeService.getAllEmployees();} }但是在測試的時候,我們并不需要使用真實的Service,我們需要Mock它 。
@RunWith(SpringRunner.class) @WebMvcTest(EmployeeRestController.class) public class EmployeeControllerIntegrationTest {@Autowiredprivate MockMvc mvc;@MockBeanprivate EmployeeService service;// write test cases here為了測試Controller,我們需要使用到@WebMvcTest,他會為Spring MVC 自動配置所需的組件。
通常情況下@WebMvcTest 會和@MockBean一起使用來提供Mock的具體實現。
@WebMvcTest也提供了自動配置的MockMvc,它為測試MVC Controller提供了更加簡單的方式,而不需要啟動完整的HTTP server。
@Test public void givenEmployees_whenGetEmployees_thenReturnJsonArray()throws Exception {Employee alex = new Employee("alex");List<Employee> allEmployees = Arrays.asList(alex);given(service.getAllEmployees()).willReturn(allEmployees);mvc.perform(get("/api/employees").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(jsonPath("$", hasSize(1))).andExpect(jsonPath("$[0].name", is(alex.getName()))); }given(service.getAllEmployees()).willReturn(allEmployees); 這一行代碼提供了mock的輸出。方面后面的測試使用。
@SpringBootTest的集成測試
上面我們講的都是單元測試,這一節我們講一下集成測試。
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = TestApplication.class) @AutoConfigureMockMvc @TestPropertySource(locations = "classpath:application-integrationtest.properties") public class EmployeeAppIntegrationTest {@Autowiredprivate MockMvc mvc;@Autowiredprivate EmployeeRepository repository; }集成測試需要使用@SpringBootTest,在@SpringBootTest中可以配置webEnvironment,同時如果我們需要自定義測試屬性文件可以使用@TestPropertySource。
下面是具體的測試代碼:
@Afterpublic void resetDb() {repository.deleteAll();}@Testpublic void givenEmployees_whenGetEmployees_thenStatus200() throws Exception {createTestEmployee("bob");createTestEmployee("alex");// @formatter:offmvc.perform(get("/api/employees").contentType(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk()).andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)).andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2)))).andExpect(jsonPath("$[0].name", is("bob"))).andExpect(jsonPath("$[1].name", is("alex")));// @formatter:on}//private void createTestEmployee(String name) {Employee emp = new Employee(name);repository.saveAndFlush(emp);}本文的例子可以參考https://github.com/ddean2009/learn-springboot2/tree/master/springboot-test
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
更多教程請參考 flydean的博客
總結
以上是生活随笔為你收集整理的Spring Boot中的测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Spring Boot中配置web a
- 下一篇: Spring Boot的TestRest