SpringBoot使用MockMVC单元测试Controller

发表于:2020-11-11 09:30

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:三号小玩家    来源:博客园

  对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。
  MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
  MockMvcBuilder是用来构造MockMvc的构造器,其主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(此种方式并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂MockMvcBuilders创建即可。
  下面就写一个简单的案例,告诉你是如何使用MockMvc进行Controller测试的。
  第一步、创建项目
  创建一个Maven项目(springboot-junit),并配置pom.xml,参照下面代码:
  <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>
  创建一个Controller类,我们在后面就测试空上Controller:
  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;
      }
  }
  第二步、编写测试类
  下面我们就是编写测试类了:
  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.4版本之前用的是SpringJUnit4ClassRunner.class
  @RunWith(SpringRunner.class)
  //SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class)
  @SpringBootTest(classes = App.class)
  //测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的
  @WebAppConfiguration
  public class HelloControllerTest {
      @Autowired
      private WebApplicationContext webApplicationContext;
      private MockMvc mockMvc;
      @Before
      public void setUp() throws Exception{
          //MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;
          mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
      }
      @Test
      public void getHello() throws Exception{
          /**
           * 1、mockMvc.perform执行一个请求。
           * 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
           * 3、ResultActions.param添加请求传值
           * 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
           * 5、ResultActions.andExpect添加执行完成后的断言。
           * 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
           *   比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
           * 5、ResultActions.andReturn表示执行完成后返回相应的结果。
           */
          MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/")
                  .param("name","lvgang")
                  .accept(MediaType.TEXT_HTML_VALUE))
                 // .andExpect(MockMvcResultMatchers.status().isOk())             //等同于Assert.assertEquals(200,status);
                 // .andExpect(MockMvcResultMatchers.content().string("hello lvgang"))    //等同于 Assert.assertEquals("hello lvgang",content);
                  .andDo(MockMvcResultHandlers.print())
                  .andReturn();
          int status=mvcResult.getResponse().getStatus();                 //得到返回代码
          String content=mvcResult.getResponse().getContentAsString();    //得到返回结果
          Assert.assertEquals(200,status);                        //断言,判断返回代码是否正确
          Assert.assertEquals("hello lvgang",content);            //断言,判断返回的值是否正确
      }
  }
  整个测试过程如下:
  1、准备测试环境
  2、通过MockMvc执行请求
  3、添加验证断言
  4、添加结果处理器
  5、得到MvcResult进行自定义断言/进行下一步的异步请求
  6、卸载测试环境
  第三步、测试结果
  通过执行HelloControllerTest,得到以下结果:
  并且把整个返回结果都打印到了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 = []
  通过以上代码,我们就完成了一个简单的案例。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号