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

Pre*_*ier 30 rest spring-mvc http-status-code-401 resttemplate

如果请求参数正常,我设计了一个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());
}
Run Code Online (Sandbox Code Playgroud)

异常日志是

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)
Run Code Online (Sandbox Code Playgroud)

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

nil*_*esh 49

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你需要在测试中做的是,在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]"));
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您遵循此模式,则CustomException是未经检查的异常.例如,您可以扩展RuntimeException.否则,异常无法传递该方法的"throws IOException". (2认同)

Ram*_*mps 29

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

restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
    protected boolean hasError(HttpStatus statusCode) {
        return false;
    }});
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说非常好.因为我使用的API返回JSON错误,抛出的异常禁止我看到它.这给了我足够的调试灵活性. (3认同)

eri*_*o07 7

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

catch(HttpStatusCodeException e) {
    log.debug("Status Code", e.getStatusCode());
}
Run Code Online (Sandbox Code Playgroud)


cha*_*ean 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()));
        }
}
Run Code Online (Sandbox Code Playgroud)