在不少Java企業級應用中,Spring佔據了很是重要的位置,這就致使了基本上的技術選型都是圍繞着Spring來, 比方說筆者最近的項目須要開發一個Restful的API接口,選型的時候就說,客戶架構師直接就拍了spring-ws,緣由呢?系統中其餘的模塊都是用的Spring-ws,保持一致,並且社區活躍,文檔豐富,遇到問題易解決。好了,入正題。
既然選定了Spring-WS, 已經TDD入魔的我,首先想到的就是我應該怎麼測試這個API接口呢? 做爲業界最成熟的框架,Spring爲測試其Web應用提供了很是好用的輔助類MockMvc。
首先,在項目的測試代碼中加入輔助Spring Web測試的庫 java
- 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格式數據的斷言。
而後,編寫測試代碼 git
- @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 {
-
- mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
- }
-
- @Test
- public void testGet() throws Exception {
-
- mockMvc.perform(get("/requests/1")
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON)
- .param("userId", "xianlinbox")
- )
-
-
- .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")
- )
-
-
- .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 = []
看完了測試, 來簡單的看下具體的實現代碼: github
- @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-restspring