• 基于Spring-WS的Restful API的集成测试


    在很多Java企业级应用中,Spring占据了非常重要的位置,这就导致了基本上的技术选型都是围绕着Spring来, 比方说笔者最近的项目需要开发一个Restful的API接口,选型的时候就说,客户架构师直接就拍了spring-ws,原因呢?系统中其他的模块都是用的Spring-ws,保持一致,而且社区活跃,文档丰富,遇到问题易解决。好了,入正题。

    既然选定了Spring-WS, 已经TDD入魔的我,首先想到的就是我应该怎么测试这个API接口呢? 作为业界最成熟的框架,Spring为测试其Web应用提供了非常好用的辅助类MockMvc。

    首先,在项目的测试代码中加入辅助Spring Web测试的库

    Gradle代码  收藏代码
    1. testCompile(  
    2.             "org.springframework:spring-test:$springVersion",  
    3.             "org.springframework.ws:spring-ws-test:2.1.0.RELEASE",  
    4.             "javax.servlet:javax.servlet-api:3.0.1",  
    5.             "com.jayway.jsonpath:json-path-assert:0.9.0"  
    6.     )  

    其中,jsonpath库的依赖是为了更好的做json格式数据的断言。

    然后,编写测试代码

    Java代码  收藏代码
    1. //指定使用SpringIntegration测试,并且制定了运行测试的ApplicationContext  
    2. @RunWith(SpringJUnit4ClassRunner.class)  
    3. @ContextConfiguration(locations = {"classpath:spring-servlet.xml"})  
    4. public class ApiControllerIntegrationTest {  
    5.   
    6.     @Autowired  
    7.     private ApiController controller;  
    8.   
    9.     private MockMvc mockMvc;  
    10.   
    11.     @Before  
    12.     public void setUp() throws Exception {  
    13.         //绑定需要测试的Controller到MockMvcshang  
    14.         mockMvc = MockMvcBuilders.standaloneSetup(controller).build();  
    15.     }  
    16.   
    17.     @Test  
    18.     public void testGet() throws Exception {  
    19.         //发出请求,在请求中可以设置一个http request可设置的所有参数  
    20.         mockMvc.perform(get("/requests/1")  
    21.                 .contentType(MediaType.APPLICATION_JSON)  
    22.                 .accept(MediaType.APPLICATION_JSON)  
    23.                 .param("userId", "xianlinbox")  
    24.         )  
    25.         //验证Respondse,status()中,可验证所有的HTTP Status CODE  
    26.         //另外,使用了jsonPath更优雅的做json属性值的验证  
    27.                 .andExpect(status().isOk())  
    28.                 .andExpect(jsonPath("$.userId").value("xianlinbox"))  
    29.                 .andExpect(jsonPath("$.requestId").value("1"))  
    30.                 .andExpect(jsonPath("$.requestType").value("GET"));  
    31.     }  
    32.   
    33.     @Test  
    34.     public void testPost() throws Exception {  
    35.         mockMvc.perform(post("/requests")  
    36.                 .contentType(MediaType.APPLICATION_JSON)  
    37.                 .accept(MediaType.APPLICATION_JSON)  
    38.                 .content("this is the message")  
    39.                 .param("userId", "xianlinbox")  
    40.         )  
    41.                 //使用print()可打印出当前测试设计的HTTP Request/Responsed的所有信息,方便定位问题  
    42.                 //Post方法的返回结果应该是202(HttpStatus.Created),对象创建成功  
    43.                 .andDo(print())  
    44.                 .andExpect(status().isCreated())  
    45.                 .andExpect(jsonPath("$.userId").value("xianlinbox"))  
    46.                 .andExpect(jsonPath("$.requestType").value("POST"))  
    47.                 .andExpect(jsonPath("$.message").value("this is the message"));  
    48.     }  
    49.   
    50. }  


    testPost方法中的print()语句打印出的效果如下:
    MockHttpServletRequest:
             HTTP Method = POST
             Request URI = /requests
              Parameters = {userId=[xianlinbox]}
                 Headers = {Content-Type=[application/json], Accept=[application/json]}

                 Handler:
                    Type = com.xianlinbox.api.ApiController
                  Method = public com.xianlinbox.api.Request com.xianlinbox.api.ApiController.post(java.lang.String,java.lang.String)

                   Async:
       Was async started = false
            Async result = null

      Resolved Exception:
                    Type = null

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

                FlashMap:

    MockHttpServletResponse:
                  Status = 201
           Error message = null
                 Headers = {Content-Type=[application/json;charset=UTF-8]}
            Content type = application/json;charset=UTF-8
                    Body = {"userId":"xianlinbox","requestId":"1","requestType":"POST","message":"this is the message"}
           Forwarded URL = null
          Redirected URL = null
                 Cookies = []

    看完了测试, 来简单的看下具体的实现代码:

    Java代码  收藏代码
    1. @Controller  
    2. public class ApiController {  
    3.   
    4.     @RequestMapping(value = "/requests/{requestId}", method = RequestMethod.GET)  
    5.     @ResponseBody  
    6.     public Request get(@PathVariable String requestId, @RequestParam(value = "userId") String userId) {  
    7.         return new Request(userId, requestId, "GET");  
    8.     }  
    9.   
    10.     @RequestMapping(value = "/requests", method = RequestMethod.POST)  
    11.     @ResponseBody  
    12.     @ResponseStatus(value = HttpStatus.CREATED)  
    13.     public Request post(@RequestParam(value = "userId") String userId, @RequestBody String content) {  
    14.         Request request = new Request(userId, "1", "POST");  
    15.         request.setMessage(content);  
    16.         return request;  
    17.     }  
    18. }  
    • 使用RequestMapping定义URL
    • 使用@ResponseBody表示返回json
    • 使用@PathVariable 获取路径参数
    • 使用@RequestParam获取request payload中的参数
    • 使用@RequestBody获取request body
    • 使用@ResponseStatus(value = HttpStatus.CREATED),定义返回的HTTP STATUS CODE



    该Demo的所有代码: https://github.com/xianlinbox/TDD_Demo/tree/master/spring-ws-rest

  • 相关阅读:
    【Liunx】centos防火墙
    【Liunx】基础命令
    【Flask】CBV模式
    【Flask】第三方插件
    【Flask】登录练习
    【Flask】特殊装饰器
    【Flask】蓝图
    Django之视图层
    Django之路由控制配置
    Django之静态文件配置
  • 原文地址:https://www.cnblogs.com/xiaohui123-com/p/6547026.html
Copyright © 2020-2023  润新知