• 测试Controller


    一、背景介绍

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

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

    二、MockMvc 使用

    2.1 构建 MockMvc

    通过 MockMvcBuilder 可以构建 MockMvc 对象,它主要有如下两个实现:

    • StandaloneMockMvcBuilder: 独立安装测试

      private MockMvc mockMvc;
      @BeforeEach
      public void setUp() {
      	mockMvc = MockMvcBuilders.standaloneSetup(new TestController()).build();
      }        
      
    • DefaultMockMvcBuilder:集成 Web 服务测试 ,建议使用这种方式

      @Autowired
      private WebApplicationContext context;
      private MockMvc mockMvc;
      @BeforeEach
      public void setUp() {
      	mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
      }  
      

    2.2 构建请求

    通过 MockMvcRequestBuilders 来构建请求,它有以下方法:

    • get
    • post
    • put
    • delete
    • ......

    2.3 执行请求

    MockMvc 通过调用 perform(RequestBuilder requestBuilder) 方法发起请求,将会返回一个操作结果 ResultActions

    2.4 操作结果处理

    ResultActions有以下三种处理:

    • ResultActions.andExpect:添加执行完成后的断言。添加 ResultMatcher 验证规则,验证控制器执行完成后结果是否正确;

    • ResultActions.andDo:添加一个结果处理器,如使用 .andDo(MockMvcResultHandlers.print()) 输出整个响应结果信息,可以在调试的时候使用。

    • ResultActions.andReturn:表示执行完成后返回相应的结果

    2.5 MvcResult

    执行完控制器后得到的整个结果,并不仅仅是返回值,其包含了测试时需要的所有信息。

    * MockHttpServletRequest getRequest():得到执行的请求;
    * MockHttpServletResponse getResponse():得到执行后的响应;
    * Object getHandler():得到执行的处理器,一般就是控制器;
    * HandlerInterceptor[] getInterceptors():得到对处理器进行拦截的拦截器;
    * ModelAndView getModelAndView():得到执行后的ModelAndView;
    * Exception getResolvedException():得到HandlerExceptionResolver解析后的异常;
    * FlashMap getFlashMap():得到FlashMap;
    * Object getAsyncResult()/Object getAsyncResult(long timeout):得到异步执行的结果;
    

    三、实例

    3.1 引入依赖

    <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>
    		<scope>test</scope>
    	</dependency>
    </dependencies>
    

    3.2 Get 请求

    1. 创建 Get 请求方法
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
    
        @GetMapping("/hello")
        public String hello(String name) {
            return "hello " + name;
        }
    }    
    
    1. 编写测试
    @SpringBootTest
    public class TestControllerTest {
    
        @Autowired
        private WebApplicationContext context;
    
        private MockMvc mockMvc;
    
        @BeforeEach
        public void setUp() {
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
        }
    
        @Test
        public void should_return_hello() throws Exception {
            String expectedResult = "hello MarkLogZhu";
    
            final String result = mockMvc.perform(
                    // GET 请求
                    get("/test/hello")
                            // 添加参数
                            .param("name", "MarkLogZhu")
            )
                    // 断言 HTTP 返回状态是 200
                    .andExpect(status().isOk())
                    // 获取返回结果对象
                    .andReturn()
                    // 将响应值以字符串形式返回
                    .getResponse().getContentAsString();
    
            assertThat(result, is(expectedResult));
        }
    }    
    

    3.3 POST 请求

    1. 编写 Post 请求
    @RestController
    @RequestMapping("/test")
    public class TestController {
        
        @PostMapping("/create")
        public User create(@RequestBody CreateUserCommand command) {
            return new User(command.getName(), command.getAge()+1);
        }
    
    }
    
    public class CreateUserCommand {
        private String name;
        private Integer age;
    
        public CreateUserCommand(){}
        public CreateUserCommand(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
        ...... get/set
    }   
    public class User {
        private String name;
        private Integer age;
    
        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
        ...... get/set    
    }    
    

    2) 编写测试

    @SpringBootTest
    public class TestControllerTest {
    
        @Autowired
        private WebApplicationContext context;
    
        private MockMvc mockMvc;
    
        @BeforeEach
        public void setUp() {
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
        }
        @Test
        public void should_create_user_success() throws Exception {
            String expectedResult = "{"name":"MarkLogZhu","age":19}";
    
            String requestJson = "{"name":"MarkLogZhu","age":18}";
    
            final String result = mockMvc.perform(
                    // POST 请求
                    post("/test/create")
                            // 设置请求内容格式为JSON
                            .contentType(MediaType.APPLICATION_JSON)
                            // 请求内容
                            .content(requestJson)
            )
                    // 获取返回结果对象
                    .andReturn()
                    // 将响应值以字符串形式返回
                    .getResponse()
                    .getContentAsString();
    
            assertThat(result, is(expectedResult));
        }
    
    }    
    
  • 相关阅读:
    [数据知识]DAMA数据管理—引论
    How to clear/delete all the partition table from a disk or partition in Linux
    Rust Safe Coding Notes
    量化交易平台
    斯坦福大学——人工智能本科4年课程清单
    去中心化数字身份DID简介——五、DID的应用
    linux c 打印时间最简单的实例
    sqlalchemy中Column的默认值属性
    Ubuntu安装jdk8的两种方式
    面试官:手撕十大排序算法,你会几种?(转)
  • 原文地址:https://www.cnblogs.com/markLogZhu/p/13685579.html
Copyright © 2020-2023  润新知