2013-03-14 34 views
26

我設計了一個web服務來在請求參數正常的情況下執行任務,或者返回401未授權的HTTP狀態碼,如果請求參數錯誤或爲空。Spring RestTemplate調用帶有錯誤的webservice並分析狀態代碼

我使用RestTemplate執行測試,並且如果web服務成功響應,我能夠驗證HTTP 200 OK狀態。但是,我無法測試HTTP 401錯誤,因爲RestTemplate本身會引發異常。

我的測試方法是

@Test 
public void testUnauthorized() 
{ 
    Map<String, Object> params = new HashMap<String, Object>(); 
    ResponseEntity response = restTemplate.postForEntity(url, params, Map.class); 
    Assert.assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); 
    Assert.assertNotNull(response.getBody()); 
} 

異常日誌

org.springframework.web.client.HttpClientErrorException: 401 Unauthorized 
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88) 
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:533) 
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:489) 
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:447) 
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:318) 

如何,如果Web服務使用HTTP狀態碼401回覆我可以測試?

+0

難道我的回答對你的工作? – nilesh 2014-09-02 13:48:14

回答

5

您可以使用彈簧測試。這是很容易:

@WebAppConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:your-context.xml") 
public class BasicControllerTest { 

     @Autowired 
     protected WebApplicationContext wac; 
     protected MockMvc mockMvc; 

     @Before 
     public void setUp() throws Exception { 
     mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 
     } 

     @Test 
     public void testUnauthorized(){ 

     mockMvc.perform(MockMvcRequestBuilders 
          .post("your_url") 
          .param("name", "values") 
     .andDo(MockMvcResultHandlers.print()) 
     .andExpect(MockMvcResultMatchers.status().isUnauthorized() 
     .andExpect(MockMvcResultMatchers.content().string(Matchers.notNullValue())); 
     } 
} 
+1

如果您需要將身份驗證添加到您的標題中,則這不起作用,因爲默認情況下,Spring不會通過過濾器運行測試。 – snowe 2015-07-22 19:40:50

44

你需要爲了攔截響應碼,身體和頭部,當你使用模板休息從服務中獲得非2xx響應代碼來實現ResponseErrorHandler。複製您需要的所有信息,將其附加到您的自定義異常並拋出,以便您可以在測試中捕獲它。

public class CustomResponseErrorHandler implements ResponseErrorHandler { 

    private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler(); 

    public boolean hasError(ClientHttpResponse response) throws IOException { 
     return errorHandler.hasError(response); 
    } 

    public void handleError(ClientHttpResponse response) throws IOException { 
     String theString = IOUtils.toString(response.getBody()); 
     CustomException exception = new CustomException(); 
     Map<String, Object> properties = new HashMap<String, Object>(); 
     properties.put("code", response.getStatusCode().toString()); 
     properties.put("body", theString); 
     properties.put("header", response.getHeaders()); 
     exception.setProperties(properties); 
     throw exception; 
    } 
} 

現在,您需要在您的測試做的是,在RestTemplate像設置此ResponseErrorHandler,

RestTemplate restclient = new RestTemplate(); 
restclient.setErrorHandler(new CustomResponseErrorHandler()); 
try { 
    POJO pojo = restclient.getForObject(url, POJO.class); 
} catch (CustomException e) { 
    Assert.isTrue(e.getProperties().get("body") 
        .equals("bad response")); 
    Assert.isTrue(e.getProperties().get("code").equals("400")); 
    Assert.isTrue(((HttpHeaders) e.getProperties().get("header")) 
        .get("fancyheader").toString().equals("[nilesh]")); 
} 
+1

請注意,如果您遵循此模式,CustomException是未經檢查的異常。例如,您可以擴展RuntimeException。否則,該異常無法通過該方法的「拋出IOException」。 – 2015-07-15 20:08:23

+0

請注意,我使用的是發佈請求 – snowe 2015-07-22 20:11:45

+0

@ snowe2010您可以執行以下操作來獲取您的HttpCustomException。 ();} catch(Exception e){if(e.getCause()instanceof HttpCustomException){ \t HttpCustomException customException =(HttpCustomException)e.getCause(); \t l.warn(「Rest custom template的自定義例外」); }} – Maximus 2015-07-23 19:57:45

24

作爲替代由Nilesh製作提出的解決方案,你也可以使用Spring類DefaultResponseErrorHandler。您還需要對其hasError(HttpStatus)方法進行拓展,以便它不會在不成功的結果上拋出異常。

restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ 
    protected boolean hasError(HttpStatus statusCode) { 
     return false; 
    }}); 
+3

這對我來說真的很好。由於我使用的API返回JSON錯誤,拋出的異常禁止我看到它。這給了我足夠的調試靈活性。 – Sion 2015-11-26 22:33:32

+1

最後你解決了我的問題。謝謝...... – KJEjava48 2016-08-26 06:42:33

7

在我休息的服務,我趕上HttpStatusCodeException,而不是Exception 因爲HttpStatusCodeException有越來越狀態碼

catch(HttpStatusCodeException e) { 
    log.debug("Status Code", e.getStatusCode()); 
} 
+1

爲快速,快速的解決方案,這很好,如果你需要訪問響應內容,你可以捕捉HttpClientErrorException和/或HttpServerErrorException,兩者都有getResponseBodyAsString()方法 – chrismarx 2016-03-30 00:59:11

+1

我的兩分錢:如果你使用TestRestTemplate類(Spring Boot),你應該使用catch(RestClientException)。 – 2016-12-02 04:57:36