Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the loopholes in Spring MVC interface

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to solve Spring MVC interface loopholes". In daily operation, I believe many people have doubts about how to solve the problem of Spring MVC interface loopholes. Xiaobian consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to solve the doubts of "how to solve Spring MVC interface loopholes". Next, please follow the editor to study!

1. Preface

Be sure to add Spring Boot Test-related components before you begin, and the following dependencies should be included in the latest version:

Org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine

two。 Test the control layer separately

If we only need to test the control layer interface (Controller) and the interface does not rely on the Spring Bean declared by @ Service, @ Component and other annotations, we can use @ WebMvcTest to enable testing only for the Web control layer, for example

@ WebMvcTest class CustomSpringInjectApplicationTests {@ Autowired MockMvc mockMvc @ SneakyThrows @ Test void contextLoads () {mockMvc.perform (MockMvcRequestBuilders.get ("/ foo/map")) .andexpect (ResultMatcher.matchAll (status () .isOk (), content () .contentType (MediaType.APPLICATION_JSON), jsonPath ("$.test") Is.is ("hello") .andDo (MockMvcResultHandlers.print ()) }}

This approach is much faster and loads only a small portion of the application. But if your approach to the service layer doesn't work, we need to test it as a whole.

3. Overall test

Most interface tests under Spring Boot are holistic and comprehensive testing, involving control layer, service layer, persistence layer and other aspects, so it is necessary to load a relatively complete Spring Boot context. At this point we can do this by declaring an abstract test base class:

Package cn.felord.custom; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; / * Test base class, * @ author felord.cn * / @ SpringBootTest @ AutoConfigureMockMvc abstract class CustomSpringInjectApplicationTests {/ * The Mock mvc. * / @ Autowired MockMvc mockMvc; / / other public dependencies and handling methods}

MockMvc is injected into Spring IoC only if @ AutoConfigureMockMvc exists.

Then write the following test code for the specific control layer:

Package cn.felord.custom; import lombok.SneakyThrows; import org.hamcrest.core.Is; import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultMatcher; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; / * Test FooController. * * @ author felord.cn * / public class FooTests extends CustomSpringInjectApplicationTests {/ * / foo/map API test. * / @ SneakyThrows @ Test void contextLoads () {mockMvc.perform (MockMvcRequestBuilders.get ("/ foo/map")) .andexpect (ResultMatcher.matchAll (status () .isOk (), content () .contentType (MediaType.APPLICATION_JSON), jsonPath ("$.test") Is.is ("bar") .andDo (MockMvcResultHandlers.print ()) }}

4. MockMvc test

In integration testing, I hope to be able to test Controller by entering URL. If you start the server and set up http client for testing, this will make testing very troublesome, for example, slow startup speed, inconvenient test verification, dependence on network environment, etc., in order to test Controller, MockMvc is introduced.

MockMvc realizes the simulation of Http request, which can directly use the form of network and convert to the call of Controller, which makes the testing speed fast, does not depend on the network environment, and provides a set of verification tools, which can make the verification of request unified and convenient. Next, let's construct a simulation request for the test step by step, assuming that we have an interface like this:

@ RestController @ RequestMapping ("/ foo") public class FooController {@ Autowired private MyBean myBean; @ GetMapping ("/ user") public Map bar (@ RequestHeader ("Api-Version") String apiVersion, User user) {Map map = new HashMap (); map.put ("test", myBean.bar ()); map.put ("version", apiVersion); map.put ("username", user.getName ()) / / todo your business return map;}}

If the parameter is set to name=felord.cn&age=18, the corresponding HTTP message is as follows:

GET / foo/user?name=felord.cn&age=18 HTTP/1.1 Host: localhost:8888 Api-Version: v1

The predictable return value is:

{"test": "bar", "version": "v1", "username": "felord.cn"}

In fact, the testing of the interface can be divided into the following steps.

Build request

MockMvcRequestBuilders is responsible for building the request, which provides the property construction of all requests, such as request method (Method), request header (Header), request body (Body), parameter (Parameters), Session, and so on. The request for the / foo/user interface can be translated into:

MockMvcRequestBuilders.get ("/ foo/user") .param ("name", "felord.cn") .param ("age", "18") .header ("Api-Version", "v1")

Execute Mock request

The MockMvc then executes the Mock request:

MockMvc.perform (MockMvcRequestBuilders.get ("/ foo/user") .param ("name", "felord.cn") .param ("age", "18") .header ("Api-Version", "v1"))

Deal with the results

The result of the request is encapsulated in a ResultActions object, which encapsulates a variety of methods that let us process the result of the Mock request.

Anticipate the results

The ResultActions#andExpect (ResultMatcher matcher) method is responsible for expecting the results of the response to see if it meets the expectations of the test. The parameter ResultMatcher is responsible for extracting the desired parts from the response object for expected comparison.

If we expect the interface / foo/user to return JSON, and the HTTP status is 200, and the response body contains the value of version=v1, we should declare:

ResultMatcher.matchAll (MockMvcResultMatchers.status () .isOk (), MockMvcResultMatchers.content () .contentType (MediaType.APPLICATION_JSON), MockMvcResultMatchers.jsonPath ("$.version", Is.is ("v1")

JsonPath is a powerful JSON parsing class library, please learn about it through its project repository https://github.com/json-path/JsonPath.

Process the response

The ResultActions#andDo (ResultHandler handler) method is responsible for printing the entire request / response or log output, stream output, which are provided by the MockMvcResultHandlers utility class. We can view the details of the request response in the above three ways.

For example, / foo/user interface:

MockHttpServletRequest: HTTP Method = GET Request URI = / foo/user Parameters = {name= [felord.cn], age= [18]} Headers = [Api-Version: "v1"] Body = null Session Attrs = {} Handler: Type = cn.felord.xbean.config.FooController Method = cn.felord.xbean.config.FooController#urlEncode (String Params) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200Error message = null Headers = [Content-Type: "application/json"] Content type = application/json Body = {"test": "bar" "version": "v1", "username": "felord.cn"} Forwarded URL = null Redirected URL = null Cookies = []

Get the returned result

If you want to further process the result of the response, you can also get the result of type MvcResult through ResultActions#andReturn () for further processing.

A complete testing process

Usually andExpect is the inevitable choice, while andDo and andReturn are useful in some scenarios, both of which are optional. Let's connect the ones above.

@ Autowired MockMvc mockMvc @ SneakyThrows @ Test void contextLoads () {mockMvc.perform (MockMvcRequestBuilders.get ("/ foo/user") .param ("name", "felord.cn") .param ("age", "18") .header ("Api-Version", "v1") .expect (ResultMatcher.matchAll (status (). IsOk ()) Content () .contentType (MediaType.APPLICATION_JSON), jsonPath ("$.version", Is.is ("v1") .andDo (MockMvcResultHandlers.print ()) }

This streaming interface unit test is also semantically easy to understand, and you can test your interface with various assertions, positive examples, and counterexamples to make your interface more robust.

At this point, the study on "how to solve the loopholes in the Spring MVC interface" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report