使用MockMVC測試Spring Boot的REST用例
MockMVC類是ofollow,noindex" target="_blank">Spring MVC 測試框架的一部分,它通過啟動一個Servlet容器幫助測試REST控制器。
在這個MockMVC教程中,我們將使用它和Spring boot的WebMvcTest類來執行Junit 測試用例,該測試用例測試為Spring boot 2 hateoas 編寫的REST 控制器方法。
Maven依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>
一個JUnit測試類來測試Spring MVC控制器請求和響應,我們可以使用下面給出的配置。
@RunWith(SpringRunner.<b>class</b>) @WebMvcTest(EmployeeRESTController.<b>class</b>) <b>public</b> <b>class</b> TestEmployeeRESTController { @Autowired <b>private</b> MockMvc mvc; }
- SpringRunner 是SpringJUnit4ClassRunner別名。它是JUnit的BlockJUnit4ClassRunner的自定義擴充套件,它通過TestContextManager和相關的支援類和註釋為標準JUnit測試提供Spring TestContext Framework的功能。
- @WebMvcTest 註釋用於Spring MVC測試。它禁用完全自動配置,而只應用與MVC測試相關的配置。
- WebMvcTest註釋將自動配置MockMvc例項。
- 使用EmployeeRESTController.classas引數,我們要求只初始化一個Web控制器,您需要使用Mock物件提供所需的剩餘依賴項。
HTTP GET
假設有一個Rest控制器:
@GetMapping(value = <font>"/employees"</font><font>) <b>public</b> EmployeeListVO getAllEmployees() { </font><font><i>//code</i></font><font> } @GetMapping(value = </font><font>"/employees/{id}"</font><font>) <b>public</b> ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable(</font><font>"id"</font><font>) <b>int</b> id) { </font><font><i>//code</i></font><font> } </font>
下面給出了相應的方法測試:
@Autowired <b>private</b> MockMvc mvc; @Test <b>public</b> <b>void</b> getAllEmployeesAPI() throws Exception { mvc.perform( MockMvcRequestBuilders .get(<font>"/employees"</font><font>) .accept(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.employees"</font><font>).exists()) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.employees<li>.employeeId"</font><font>).isNotEmpty()); } @Test <b>public</b> <b>void</b> getEmployeeByIdAPI() throws Exception { mvc.perform( MockMvcRequestBuilders .get(</font><font>"/employees/{id}"</font><font>, 1) .accept(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.employeeId"</font><font>).value(1)); } </font>
HTTP POST
案例:
@PostMapping(value = <font>"/employees"</font><font>) <b>public</b> ResponseEntity<EmployeeVO> addEmployee (@Valid @RequestBody EmployeeVO employee) { </font><font><i>//code</i></font><font> <b>return</b> <b>new</b> ResponseEntity<EmployeeVO>(employee, HttpStatus.CREATED); } </font>
對於post json請求的相應spring springmvc測試如下:
@Autowired <b>private</b> MockMvc mvc; @Test <b>public</b> <b>void</b> createEmployeeAPI() throws Exception { mvc.perform( MockMvcRequestBuilders .post(<font>"/employees"</font><font>) .content(asJsonString(<b>new</b> EmployeeVO(<b>null</b>, </font><font>"firstName4"</font><font>, </font><font>"lastName4"</font><font>, </font><font>"[email protected]"</font><font>))) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.employeeId"</font><font>).exists()); } <b>public</b> <b>static</b> String asJsonString(<b>final</b> Object obj) { <b>try</b> { <b>return</b> <b>new</b> ObjectMapper().writeValueAsString(obj); } <b>catch</b> (Exception e) { <b>throw</b> <b>new</b> RuntimeException(e); } } </font>
HTTP PUT
HTTP API在控制器中定義為:
@PutMapping(value = <font>"/employees/{id}"</font><font>) <b>public</b> ResponseEntity<EmployeeVO> updateEmployee (@PathVariable(</font><font>"id"</font><font>) <b>int</b> id, @Valid @RequestBody EmployeeVO employee) { </font><font><i>//code</i></font><font> <b>return</b> <b>new</b> ResponseEntity<EmployeeVO>(emp, HttpStatus.OK); } </font>
相應的方法測試是
@Test <b>public</b> <b>void</b> updateEmployeeAPI() throws Exception { mvc.perform( MockMvcRequestBuilders .put(<font>"/employees/{id}"</font><font>, 2) .content(asJsonString(<b>new</b> EmployeeVO(2, </font><font>"firstName2"</font><font>, </font><font>"lastName2"</font><font>, </font><font>"[email protected]"</font><font>))) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.firstName"</font><font>).value(</font><font>"firstName2"</font><font>)) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.lastName"</font><font>).value(</font><font>"lastName2"</font><font>)) .andExpect(MockMvcResultMatchers.jsonPath(</font><font>"$.email"</font><font>).value(</font><font>"[email protected]"</font><font>)); } </font>
HTTP DELETE:
@DeleteMapping(value = <font>"/employees/{id}"</font><font>) <b>public</b> ResponseEntity<HttpStatus> removeEmployee (@PathVariable(</font><font>"id"</font><font>) <b>int</b> id) { </font><font><i>//code</i></font><font> <b>return</b> <b>new</b> ResponseEntity<HttpStatus>(HttpStatus.ACCEPTED); } </font>
相應的方法測試是:
@Test <b>public</b> <b>void</b> deleteEmployeeAPI() throws Exception { mvc.perform( MockMvcRequestBuilders.delete(<font>"/employees/{id}"</font><font>, 1) ) .andExpect(status().isAccepted()); } </font>