Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring RestTemplate invoking webservice with errors and analyze status code

I designed a webservice to perform a task if request parameters are OK, or return 401 Unauthorized HTTP status code if request parameters are wrong or empty.

I'm using RestTemplate to perform a test and I'm able to verify the HTTP 200 OK status if the webservice replies with success. I am however unable to test for HTTP 401 error because RestTemplate itself throws an exception.

My test method is

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

Exception log is

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) 

How I can test if webservice replies with a HTTP status code 401?

like image 413
Premier Avatar asked Mar 14 '13 08:03

Premier


People also ask

How do I get error from RestTemplate?

Default Error Handling By default, the RestTemplate will throw one of these exceptions in the case of an HTTP error: HttpClientErrorException – in the case of HTTP status 4xx. HttpServerErrorException – in the case of HTTP status 5xx. UnknownHttpStatusCodeException – in the case of an unknown HTTP status.

Why RestTemplate is deprecated?

RestTemplate provides a synchronous way of consuming Rest services, which means it will block the thread until it receives a response. RestTemplate is deprecated since Spring 5 which means it's not really that future proof. First, we create a Spring Boot project with the spring-boot-starter-web dependency.

How do I handle HttpStatusCodeException?

You should catch a HttpStatusCodeException exception: try { restTemplate. exchange(...); } catch (HttpStatusCodeException exception) { int statusCode = exception. getStatusCode().


2 Answers

You need to implement ResponseErrorHandler in order to intercept response code, body, and header when you get non-2xx response codes from the service using rest template. Copy all the information you need, attach it to your custom exception and throw it so that you can catch it in your test.

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;     } } 

Now what you need to do in your test is, set this ResponseErrorHandler in RestTemplate like,

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]")); } 
like image 154
nilesh Avatar answered Sep 22 '22 16:09

nilesh


As an alternative to the solution presented by nilesh, you could also use spring class DefaultResponseErrorHandler. You also need to ovveride its hasError(HttpStatus) method so it does not throw exception on non-successful result.

restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){     protected boolean hasError(HttpStatus statusCode) {         return false;     }}); 
like image 37
Ramps Avatar answered Sep 22 '22 16:09

Ramps