对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立HTTP Client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。

MockMVC实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

MockMVCBuilder是用来构造MockMVC的构造器,其主要有两个实现:StandaloneMockMVCBuilder和DefaultMockMVCBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(此种方式并不会集成真正的Web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂MockMVCBuilders创建即可。

下面就写一个简单的案例,告诉你是如何使用MockMVC进行Controller测试的。



springboot controller mock单元测试 post_springframework引入不进来

0

1

创建项目

创建一个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.0modelVersion>  <groupId>org.lvganggroupId>  <artifactId>springboot-junitartifactId>  <version>1.0-SNAPSHOTversion>  <packaging>jarpackaging>  <name>springboot-junitname>  <url>http://maven.apache.orgurl>  <parent>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-parentartifactId>    <version>2.1.3.RELEASEversion>  parent>  <properties>    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>  properties>  <dependencies>    <dependency>      <groupId>org.springframework.bootgroupId>      <artifactId>spring-boot-starter-webartifactId>    dependency>    <dependency>      <groupId>org.springframework.bootgroupId>      <artifactId>spring-boot-starter-testartifactId>    dependency>  dependencies>project>

创建一个Controller类,我们在后面就测试空上Controller

package org.lvgang;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController {    @RequestMapping("/")    public String hello(String name){        return "hello "+name;    }}



springboot controller mock单元测试 post_springframework引入不进来

0

2

编写测试类

下面我们就是编写测试类了:

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类型的@WebAppConfigurationpublic 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、卸载测试环境



springboot controller mock单元测试 post_springframework引入不进来

0

3

测试结果

通过执行HelloControllerTest,得到以下结果:

springboot controller mock单元测试 post_spring_04

并且把整个返回结果都打印到了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 = nullResolved Exception:             Type = nullModelAndView:        View name = null             View = null            Model = nullFlashMap:       Attributes = nullMockHttpServletResponse:           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 = []

通过以上代码,我们就完成了一个简单的案例。

springboot controller mock单元测试 post_spring_05