2013-03-14 11 views
26

Ich habe einen Webservice entwickelt, um eine Aufgabe auszuführen, wenn Anfrageparameter OK sind, oder 401 Nicht autorisierten HTTP-Statuscode zurückgeben, wenn Anfrageparameter falsch oder leer sind.Spring RestTemplate Webservice mit Fehlern aufrufen und Statuscode analysieren

Ich verwende RestTemplate, um einen Test durchzuführen, und ich kann den HTTP 200 OK-Status überprüfen, wenn der Webservice mit Erfolg antwortet. Ich bin jedoch nicht in der Lage, HTTP 401-Fehler zu testen, da RestTemplate selbst eine Ausnahme auslöst.

Meine Testmethode ist

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

Ausnahmeprotokoll

ist
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) 

Wie ich testen kann, wenn Webservice mit einem HTTP-Statuscode antwortet 401?

+0

Hat meine Antwort für Sie funktioniert? – nilesh

Antwort

5

Sie können einen Federtest verwenden. Es ist viel einfacher:

@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

Dies funktioniert nicht, wenn Sie Ihren Kopfzeilen eine Authentifizierung hinzufügen müssen, da spring standardmäßig keine Tests über Filter ausführt. – snowe

44

Sie müssen ResponseErrorHandler implementieren, um Antwortcode abzufangen, Körper und Kopf, wenn Sie nicht-2xx Antwortcodes aus dem Dienst mit Rest-Vorlage erhalten. Kopieren Sie alle benötigten Informationen, hängen Sie sie an Ihre benutzerdefinierte Ausnahme an und werfen Sie sie so, dass Sie sie in Ihrem Test abfangen können.

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

Nun, was Sie brauchen in Ihrem Test zu tun ist, um diesen ResponseErrorHandler in RestTemplate gesetzt wie

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

Beachten Sie, dass CustomException eine nicht ausgewählte Ausnahme ist, wenn Sie diesem Muster folgen. Sie können beispielsweise RuntimeException erweitern. Andernfalls kann die Ausnahme die "throws IOException" dieser Methode nicht übergeben. –

+0

Hinweis: Ich verwende eine Postanforderung – snowe

+0

@ snowe2010 Sie können Folgendes tun, um Ihre HttpCustomException zu erhalten. ------> catch (Ausnahme e) {if (e.getCause() instanceof HttpCustomException) { \t HttpCustomException customException = (HttpCustomException) e.getCause(); \t l.warn ("Benutzerdefinierte Ausnahme für Rest-Vorlage"); }} – Maximus

24

Als Alternative zu der Lösung von nilesh präsentiert, könnten Sie auch Feder Klasse DefaultResponseErrorHandler verwenden. Sie müssen auch die hasError (HttpStatus) -Methode überschreiben, damit bei nicht erfolgreichen Ergebnissen keine Ausnahme ausgelöst wird.

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

Das hat wirklich gut für mich funktioniert. Da die von mir verwendete API einen JSON-Fehler zurückgibt, untersagte mir die ausgelöste Ausnahme das Anzeigen. Das gab mir genug Flexibilität zum Debuggen. – Sion

+1

Endlich löste ich mein Problem.Vielen Dank .... – KJEjava48

7

In meiner Ruhe Service ertappe ich HttpStatusCodeException statt Exception seit HttpStatusCodeException eine Methode hat den Statuscode

für das Erhalten
catch(HttpStatusCodeException e) { 
    log.debug("Status Code", e.getStatusCode()); 
} 
+1

für eine schnelle, schnelle Lösung, das funktioniert gut, und wenn Sie auf den Inhalt der Antwort zugreifen müssen, können Sie nur HttpClientErrorException und/oder die HttpServerErrorException abfangen, die beide haben Die Methode getResponseBodyAsString() – chrismarx

+1

Meine zwei Cent: Wenn Sie die TestRestTemplate-Klasse (Spring Boot) verwenden, sollten Sie catch (RestClientException) verwenden. –

2

Seit dem Frühjahr 4.3 gibt es eine RestClientResponseException ist die tatsächliche HTTP-Antwortdaten enthalten, wie Statuscode, Antworttext und Header. Und du kannst es fangen.

RestClientResponseException Java Doc