既然选定了Spring-WS, 已经TDD入魔的我,首先想到的就是我应该怎么测试这个API接口呢? 作为业界最成熟的框架,Spring为测试其Web应用提供了非常好用的辅助类MockMvc。
首先,在项目的测试代码中加入辅助Spring Web测试的库
testCompile( "org.springframework:spring-test:$springVersion", "org.springframework.ws:spring-ws-test:2.1.0.RELEASE", "javax.servlet:javax.servlet-api:3.0.1", "com.jayway.jsonpath:json-path-assert:0.9.0" )其中,jsonpath库的依赖是为了更好的做json格式数据的断言。
然后,编写测试代码
//指定使用SpringIntegration测试,并且制定了运行测试的ApplicationContext @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-servlet.xml"}) public class ApiControllerIntegrationTest { @Autowired private ApiController controller; private MockMvc mockMvc; @Before public void setUp() throws Exception { //绑定需要测试的Controller到MockMvcshang mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void testGet() throws Exception { //发出请求,在请求中可以设置一个http request可设置的所有参数 mockMvc.perform(get("/requests/1") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .param("userId", "xianlinbox") ) //验证Respondse,status()中,可验证所有的HTTP Status CODE //另外,使用了jsonPath更优雅的做json属性值的验证 .andExpect(status().isOk()) .andExpect(jsonPath("$.userId").value("xianlinbox")) .andExpect(jsonPath("$.requestId").value("1")) .andExpect(jsonPath("$.requestType").value("GET")); } @Test public void testPost() throws Exception { mockMvc.perform(post("/requests") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("this is the message") .param("userId", "xianlinbox") ) //使用print()可打印出当前测试设计的HTTP Request/Responsed的所有信息,方便定位问题 //Post方法的返回结果应该是202(HttpStatus.Created),对象创建成功 .andDo(print()) .andExpect(status().isCreated()) .andExpect(jsonPath("$.userId").value("xianlinbox")) .andExpect(jsonPath("$.requestType").value("POST")) .andExpect(jsonPath("$.message").value("this is the message")); } }
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 = []
看完了测试, 来简单的看下具体的实现代码:
@Controller public class ApiController { @RequestMapping(value = "/requests/{requestId}", method = RequestMethod.GET) @ResponseBody public Request get(@PathVariable String requestId, @RequestParam(value = "userId") String userId) { return new Request(userId, requestId, "GET"); } @RequestMapping(value = "/requests", method = RequestMethod.POST) @ResponseBody @ResponseStatus(value = HttpStatus.CREATED) public Request post(@RequestParam(value = "userId") String userId, @RequestBody String content) { Request request = new Request(userId, "1", "POST"); request.setMessage(content); return request; } }
- 使用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