springmvc/springboot开发restful API, 使用MockMVC 编写测试用例

摘要:
id=1&名称=tom详细信息GET/user/1创建POST/user修改PUT/user删除Delete/user/1 rest界面设计Reference://github.com/coinflex exchange/API1,Rest Concept,2)使用HTTP方法描述行为;DELETE用于删除资源。3.REST的荣耀REST是一种软件接口设计模型。使用http方法执行不同的操作。

  非rest的url写法:

查询  GET /user/query?name=tom
详情  GET /user/getinfo?id=1
创建  POST /user/create?name=tom
修改  POST /user/update?id=1&name=tom
删除  GET /user/delete?id=1

  rest风格的写法

查询  GET /user?name=tom
详情  GET /user/1
创建  POST /user
修改  PUT /user
删除  DELETE /user/1

rest接口设计参考:https://github.com/huobiapi/API_Docs/wiki/REST_api_reference

https://github.com/huobiapi/API_Docs

coinflext api: https://github.com/coinflex-exchange/API

1、Rest概念,来自百度百科

  REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

  目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。

  

2、RESTful API的要求

  1)用URL描述资源;

  2)使用HTTP方法描述行为;使用HTTP状态码来表示不同的结果;

  3)使用json来交互数据;

  4)RESTful只是一种风格,并不是强制的标准。

  总结:使用URL定位资源,使用HTTP方法操作资源。

GET     用来获取资源;
POST    用来新建资源(也可以用于更新资源);
PUT     用来更新资源;
DELETE  用来删除资源

3、Glory of REST

  REST是一种软件接口设计的模型。REST 成熟度模型:(搜索关键字:steps toward the glory of REST)

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第1张

  

  level0: 使用http作为传输方式;

  level1: 引入资源概念,每个资源都有对应的URL;

  level2: 使用http方法进行不同的操作,使用http状态码来表示不同的结果。

  level3: 使用超媒体,在资源的表达中包含了链接信息。

4、springmvc/springboot开发restful API

  IndexController

@RestController
public class IndexController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/user/{id}")
    public Object getUserById(@PathVariable Integer id) {
        return userService.getUserById(id);
    }
}

  测试结果:

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第2张

5、使用MockMVC 编写测试用例(单元测试)

  参考:https://www.cnblogs.com/xy-ouyang/p/10681965.html

  选中IndexController,右键/new/Junit Test Case

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第3张

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第4张

   测试用例代码:

package com.imooc.controller;

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.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
 * @author oy
 * @date 2019年6月22日 下午11:14:56
 * @version 1.0.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(MockMvcRequestBuilders.get("/user/1")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(MockMvcResultHandlers.print()) // 打印信息
                .andExpect(MockMvcResultMatchers.status().isOk()) // 期望返回的状态码为200
                .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
                .andExpect(MockMvcResultMatchers.jsonPath("$.username").value("张三")) // 期望返回的json数据中username字段的值为"张三"
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

   控制台打印结果:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /user/1
       Parameters = {}
          Headers = {Content-Type=[application/x-www-form-urlencoded]}

Handler:
             Type = com.imooc.controller.IndexController
           Method = public java.lang.Object com.imooc.controller.IndexController.getUserById(java.lang.Integer)

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=[application/json;charset=UTF-8]}
     Content type = application/json;charset=UTF-8
             Body = {"username":"张三","password":"123"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
mvcResult: {"username":"张三","password":"123"}

  

  测试用例的代码简洁写法:使用静态导入

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第5张

package com.imooc.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

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.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
 * @author oy
 * @date 2019年6月22日 下午11:14:56
 * @version 1.0.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(get("/user/1")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(print()) // 打印信息
                .andExpect(status().isOk()) // 期望返回的状态码为200
                .andExpect(jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
                .andExpect(jsonPath("$.username").value("张三"))
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

6、@PageableDefault指定默认的分页参数

springmvc/springboot开发restful API, 使用MockMVC 编写测试用例第6张

   测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(get("/user/1")
//                .param("page", "2")
//                .param("size", "10")
//                .param("sort", "id,desc")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(print()) // 打印信息
                .andExpect(status().isOk()) // 期望返回的状态码为200
                .andExpect(jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
                .andExpect(jsonPath("$.username").value("张三"))
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

  IndexController

@RestController
public class IndexController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/user/{id}")
    public Object getUserById(@PathVariable Integer id, 
            @PageableDefault(page = 1, size = 10, sort = "id,asc") Pageable pageable) {
        
        String str = ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE);
        System.out.println(str);
        
        return userService.getUserById(id);
    }
}

  控制台打印结果:

org.springframework.data.domain.PageRequest@7d522180[
  sort=id,asc: ASC
  page=1
  size=10
]

7、测试用例中jsonpath的用法

  github上面搜索jsonpath ==> https://github.com/json-path/JsonPath

  

8、@PathVariable 以及url映射中使用正则表达式

@GetMapping("/user/{id:\d+}")
public Object getUserById(@PathVariable Integer id) {
    return userService.getUserById(id);
}

  此时,请求url为 /user/a 时,报404。

参考:

  1)详解REST架构风格:http://www.uml.org.cn/zjjs/201805142.asp

  2)REST,以及RESTful的讲解:https://blog.csdn.net/qq_21383435/article/details/80032375

  3) 阮一峰:RESTful API 设计指南

免责声明:文章转载自《springmvc/springboot开发restful API, 使用MockMVC 编写测试用例》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【Python学习笔记】之格式化输入输出C#获取指定路径下的文件信息下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

自动化运维工具puppet详解(一)

一、puppet 介绍   1、puppet是什么   puppet是一个IT基础设施自动化管理工具,它能够帮助系统管理员管理基础设施的整个生命周期: 供应(provisioning)、配置(configuration)、联动(orchestration)及报告(reporting)。  基于puppet ,可实现自动化重复任务、快速部署关键性应用以及在本...

Kubernetes理论01

1、Kubernetes是什么 •Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。•K8S用于容器化应用程序的部署,扩展和管理。•K8S提供了容器编排,资源调度,弹性伸缩,部署管理,服务发现等一系列功能。•Kubernetes目标是让部署容器化应用简单高效。官方网站:http://www.kuber...

Scrapy爬虫的暂停和启动

scrapy的每一个爬虫,暂停时可以记录暂停状态以及爬取了哪些url,重启时可以从暂停状态开始爬取过的URL不在爬取 实现暂停与重启记录状态 方法一: 1、首先cd进入到scrapy项目里(当然你也可以通过编写脚本Python文件直接在pycharm中运行) 2、在scrapy项目里创建保存记录信息的文件夹 3、执行命令:   scrapy craw...

FSA/FSM/FST

有限状态机 Finite state machine 可以用来紧密的存储有序集合和有序键值对,并实现快速搜索怎样用FSM来作为数据结构存储这样的数据?什么是有序集合? 有序集合中的键按照字典顺序排序,典型的应用是BST/BTREE什么是无序集合? 典型的应用是HashTable 确定无环有限状态接收器 FSA (deterministic acyclic...

springboot 错误记录

1.拦截器中handler cannot be cast to HandlerMethod java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframewo...

keycloak~自定义rest接口

rest资源 对于我们集成keycloak来说,你可能会遇到它没有实现的功能,这时需要对kc进行扩展,资源的扩展是其中一个方面,它需要实现RealmResourceProvider和RealmResourceProviderFactory两个接口,然后在KC启动之后,它可以被注册到IOC容器里,方便以后我们直接使用。 KC里的扩展是开闭原则OCP的完美体现...