SpringBoot uses MockMVC to unit test the Controller

During the integration test of the module, you want to be able to test the Controller by entering the URL. If you start the server and establish an http client for testing, it will make the test very troublesome. For example, the startup speed is slow, the test verification is inconvenient, and it depends on the network environment. This will make the test impossible. In order to test the Controller, you can solve it by introducing MockMVC.

   MockMvc realizes the simulation of Http request, and can directly use the form of network to convert to the call of Controller, which can make the test fast and independent of the network environment, and provides a set of verification tools, which can make the verification of request unified and convenient.

MockMvcBuilder is a constructor used to construct MockMvc. It mainly has two implementations: StandaloneMockMvcBuilder and DefaultMockMvcBuilder, which correspond to two test methods, namely, independent installation and integrated web environment test (this method will not integrate the real web environment, but conduct simulation test through the corresponding Mock API without starting the server). For us, we can directly use the static factory MockMvcBuilders to create it.

Here is a simple case to tell you how to use MockMvc to test the Controller

Step 1: create a project

Create a Maven project (springboot JUnit) and configure POM XML, refer to the following code

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.lvgang</groupId>
  <artifactId>springboot-junit</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>springboot-junit</name>
  <url>http://maven.apache.org</url>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
  </dependencies>
</project>

Create a Controller class, and we will test the air Controller later

package org.lvgang;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String hello(String name){
        return "hello "+name;
    }

}

Step 2: write test classes

Let's write the test class

package org.lvgang;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

//SpringBoot1. Before version 4, spring JUnit 4classrunner was used class
@RunWith(SpringRunner.class)
//SpringBoot1. Before version 4, @ SpringApplicationConfiguration(classes = Application.class) was used
@SpringBootTest(classes = App.class)
//Used by the test environment to indicate that the ApplicationContext used by the test environment will be of WebApplicationContext type
@WebAppConfiguration
public class HelloControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception{
        //MockMvcBuilders.webAppContextSetup(WebApplicationContext context): specify WebApplicationContext, and the corresponding controller and MockMvc will be obtained from the context;
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//This is recommended
    }

    @Test
    public void getHello() throws Exception{

        /**
         * 1,mockMvc.perform Execute a request.
         * 2,MockMvcRequestBuilders.get("XXX")Construct a request.
         * 3,ResultActions.param Add request value transfer
         * 4,ResultActions.accept(MediaType.TEXT_HTML_VALUE))Set return type
         * 5,ResultActions.andExpect Add assertions after execution is complete.
         * 6,ResultActions.andDo Add a result processor to indicate what to do with the result
         *   Mvhandlers is used in this way Print () outputs the whole response result information.
         * 5,ResultActions.andReturn Indicates that the corresponding result is returned after execution.
         */

        MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/")
                .param("name","lvgang")
                .accept(MediaType.TEXT_HTML_VALUE))
               // .andExpect(MockMvcResultMatchers.status().isOk()) / / equivalent to assert assertEquals(200,status);
               // .andExpect(MockMvcResultMatchers.content().string("hello lvgang") / / equivalent to assert assertEquals("hello lvgang",content);
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        int status=mvcResult.getResponse().getStatus();                 //Get return code
        String content=mvcResult.getResponse().getContentAsString();    //Get the return result

        Assert.assertEquals(200,status);                        //Assert to determine whether the return code is correct
        Assert.assertEquals("hello lvgang",content);            //Assertion to determine whether the returned value is correct
    }
}

The whole test process is as follows:

1. Prepare test environment

2. Execute request via MockMvc

3. Add validation assertion

4. Add result processor

5. Get MvcResult for user-defined assertion / asynchronous request for the next step

6. Uninstall test environment

Step 3: test results

By executing HelloControllerTest, the following results are obtained:

And the whole returned result is printed into the Console

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /
       Parameters = {name=[lvgang]}
          Headers = {Accept=[text/html]}

Handler:
             Type = org.lvgang.HelloController
           Method = public java.lang.String org.lvgang.HelloController.hello(java.lang.String)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[text/html;charset=UTF-8], Content-Length=[12]}
     Content type = text/html;charset=UTF-8
             Body = hello lvgang
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

Through the above code, we have completed a simple case.

Attachment:

RequestBuilder/MockMvcRequestBuilders:

In the above test class, we use the class mockmvcrequebuilders to build requests. This class has the following main API s:

MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables): according to uri Templates and uri The variable is worth one GET Request mode MockHttpServletRequestBuilder;as get(/user/{id}, 1L);
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables): with get Similar, but yes POST method;
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables): with get Similar, but yes PUT method;
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) : with get Similar, but yes DELETE method;
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables): with get Similar, but yes OPTIONS method;
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables):  Provide your own Http Request method and uri Templates and uri Variables, as above API It's all entrusted to this API;
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables): The request for file upload method is obtained MockMultipartHttpServletRequestBuilder;
RequestBuilder asyncDispatch(final MvcResult mvcResult): Create a request that starts asynchronous processing from MvcResult For asynchronous dispatch RequestBuilder;

Mockmvcrquestbuilders obtains two types of builders through methods: MockHttpServletRequestBuilder and MockMultipartHttpServletRequestBuilder (upload file)

MockHttpServletRequestBuilder:

MockHttpServletRequestBuilder mainly has the following API s:

MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders): Add header information;
MockHttpServletRequestBuilder contentType(MediaType mediaType): Specifies the of the request contentType Header information;
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes): Specifies the of the request Accept Header information;
MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content): Specify request Body Body content;
MockHttpServletRequestBuilder param(String name,String... values): Request incoming parameters
MockHttpServletRequestBuilder cookie(Cookie... cookies): Specifies the of the request Cookie;
MockHttpServletRequestBuilder locale(Locale locale): Specifies the of the request Locale;
MockHttpServletRequestBuilder characterEncoding(String encoding): Specify the character encoding of the request;
MockHttpServletRequestBuilder requestAttr(String name, Object value) : Set request attribute data;
MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes): Set request session Attribute data;
MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes): Specifies the of the request flash Information, such as attribute information after resetting;
MockHttpServletRequestBuilder session(MockHttpSession session) : Specifies the of the request Session;
MockHttpServletRequestBuilder principal(Principal principal) : Specifies the of the request Principal;
MockHttpServletRequestBuilder contextPath(String contextPath) : Specifies the context path of the request, which must be in“/"And cannot begin with“/"ending;
MockHttpServletRequestBuilder pathInfo(String pathInfo) : The requested path information must be in“/"start;
MockHttpServletRequestBuilder secure(boolean secure): Whether the request uses a secure channel;
MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor): The post processor of the request is used to customize some extension points of request processing;

MockMultipartHttpServletRequestBuilder:

MockMultipartHttpServletRequestBuilder inherits from MockHttpServletRequestBuilder and provides the following API s:

MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file): Specify the file to upload;

ResultActions:

Call mockmvc After performing (requestbuilder, requestbuilder), you will get ResultActions. Through ResultActions, you can complete the following three things:

ResultActions andExpect(ResultMatcher matcher) : Add verification assertion to judge whether the result after executing the request is expected;
ResultActions andDo(ResultHandler handler) : Add a result processor to perform actions after successful verification, such as output request/The result information is used for debugging;
MvcResult andReturn() : Returns the result after successful verification MvcResult;For custom validation/Asynchronous processing in the next step;

ResultMatcher/MockMvcResultMatchers:

ResultMatcher is used to match the result verification after the request is executed. It is a match(MvcResult result) assertion method. If the matching fails, the corresponding exception will be thrown; In such cases and for use, please check by yourself. The following API s are provided:

HandlerResultMatchers handler(): Requested Handler Validators, such as verifying processor types/Method name; Here Handler In fact, it is the controller that processes the request;
RequestResultMatchers request(): obtain RequestResultMatchers Verifier;
ModelResultMatchers model(): Get the model verifier;
ViewResultMatchers view(): Get the view verifier;
FlashAttributeResultMatchers flash(): obtain Flash Attribute verification;
StatusResultMatchers status(): Get the response state verifier;
HeaderResultMatchers header(): Get a response Header Verifier;
CookieResultMatchers cookie(): Get a response Cookie Verifier;
ContentResultMatchers content(): Get the response content verifier;
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher): obtain Json Expression verifier;
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args): obtain Xpath Expression verifier;
ResultMatcher forwardedUrl(final String expectedUrl): Verify the information forwarded after processing the request url(Absolute match);
ResultMatcher forwardedUrlPattern(final String urlPattern): Verify the information forwarded after processing the request url(Ant Style pattern matching,@since spring4);
ResultMatcher redirectedUrl(final String expectedUrl): Verify the redirected after processing the request url(Absolute match);

ResultMatcher redirectedUrlPattern(final String expectedUrl): Verify the redirected after processing the request url(Ant Style pattern matching,@since spring4);


https://my.oschina.net/sdlvzg/blog/1594821

Posted by JsusSalv on Fri, 13 May 2022 10:03:33 +0300