首页 文章

Spring RestTemplate调用带有错误的webservice并分析状态代码

提问于
浏览
30

如果请求参数正常,我设计了一个web服务来执行任务,如果请求参数错误或为空,我会返回401 Unauthorized HTTP状态代码 .

我正在使用 RestTemplate 来执行测试,如果webservice成功回复,我就能验证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)

我如何测试webservice是否回复了HTTP状态码401?

5 回答

  • 5

    当您使用rest模板从服务获得非2xx响应代码时,您需要实现 ResponseErrorHandler 以拦截响应代码,正文和 Headers . 复制您需要的所有信息,将其附加到您的自定义异常并抛出它,以便您可以在测试中捕获它 .

    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]"));
    }
    
  • 7

    作为nilesh提供的解决方案的替代方案,您还可以使用spring类DefaultResponseErrorHandler . 您还需要遍历其hasError(HttpStatus)方法,以便它不会在非成功结果上抛出异常 .

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

    在我的休息服务中,我 grab HttpStatusCodeException 而不是 Exception ,因为 HttpStatusCodeException 有一个获取状态代码的方法

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

    你可以使用 spring 测试 . 它更容易:

    @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()));
            }
    }
    
  • 48

    从Spring 4.3开始,有一个 RestClientResponseException 包含实际的HTTP响应数据,例如状态代码,响应正文和 Headers . 你可以 grab 它 .

    RestClientResponseException Java Doc

相关问题