2013-03-14 18 views
26

Zaprojektowałem webservice do wykonania zadania, jeśli parametry żądania są OK, lub zwracają 401 Nieautoryzowany kod statusu HTTP, jeśli parametry żądania są błędne lub puste.Spring RestTemplate wywołując webservice z błędami i analizując kod stanu

Używam RestTemplate do wykonania testu i jestem w stanie zweryfikować status HTTP 200 OK, jeśli usługa odpowie poprawnie. Nie mogę jednak przetestować błędu HTTP 401, ponieważ sam RestTemplate zgłasza wyjątek.

Moja metoda badawcza jest

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

Wyjątek dziennika jest

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) 

Jak mogę sprawdzić, czy usługa odpowiada z kodem stanu HTTP 401?

+0

Czy moja odpowiedź działa dla Ciebie? – nilesh

Odpowiedz

5

Możesz użyć testu sprężynowego. Jest to o wiele łatwiejsze:

@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

To nie działa, jeśli musisz dodać uwierzytelnianie do nagłówków, ponieważ wiosna nie uruchamia testów domyślnie przez filtry. – snowe

44

Trzeba wdrożyć ResponseErrorHandler w celu przechwycenia kodu odpowiedzi, ciało i nagłówek kiedy masz non-2xx kody odpowiedzi z usługi za pomocą szablonu odpoczynek. Skopiuj wszystkie potrzebne informacje, dołącz je do niestandardowego wyjątku i wyrzuć, aby można było go złapać w teście.

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

Teraz co trzeba zrobić w swoim badaniu jest, ustaw tę ResponseErrorHandler w RestTemplate jak,

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

Należy zauważyć, że w przypadku zastosowania się do tego wzorca wyjątek CustomException jest niezaznaczonym wyjątkiem. Na przykład można rozszerzyć wyjątek RuntimeException. W przeciwnym razie wyjątek nie może zostać zaliczony przez "throws IOException" tej metody. –

+0

Uwaga, używam żądania pocztowego – snowe

+0

@ snowe2010 Można wykonać następujące czynności, aby uzyskać wyjątek HttpCustomException. ------> catch (wyjątek e) {jeśli (e.getCause() wystąpienie HttpCustomException) { \t HttpCustomException customException = (HttpCustomException) e.getCause(); \t l.warn ("Niestandardowy wyjątek dla szablonu odpoczynku"); }} – Maximus

24

Jako alternatywę dla rozwiązania przedstawionego przez Nilesh, można również użyć sprężyny klasy DefaultResponseErrorHandler. Trzeba również ovveride jego metodę hasError (HttpStatus), aby nie wyrzucała wyjątku w przypadku nieudanych wyników.

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

To zadziałało bardzo dobrze dla mnie. Ponieważ używany przeze mnie interfejs API zwraca błąd JSON, zgłoszony wyjątek uniemożliwiał mi jego wyświetlenie. Dało mi to dość elastyczności do debugowania. – Sion

+1

Wreszcie rozwiązałeś mój problem.Dziękuję ... – KJEjava48

7

W mojej służbie spoczynku złapię HttpStatusCodeException zamiast Exception od HttpStatusCodeException ma metodę uzyskania kodu stanu

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

za szybkie, szybkie rozwiązanie, działa to dobrze, a jeśli potrzebujesz dostępu do treści odpowiedzi, możesz po prostu złapać wyjątek HttpClientErrorException i/lub HttpServerErrorException, które mają Metoda getResponseBodyAsString() – chrismarx

+1

Moje dwa centy: jeśli używasz klasy TestRestTemplate (Spring Boot), powinieneś użyć catch (RestClientException). –

Powiązane problemy