J'ai conçu un service Web pour effectuer une tâche si les paramètres de la demande sont OK, ou retourner le code d'état HTTP 401 non autorisé si les paramètres de la demande sont incorrects ou vides.
J'utilise RestTemplate
pour effectuer un test et je peux vérifier l'état HTTP 200 OK si le service Web répond avec succès. Je ne suis cependant pas en mesure de tester l'erreur HTTP 401 car RestTemplate
lui-même lève une exception.
Ma méthode de test est
@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());
}
Le journal des exceptions est
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)
Comment puis-je tester si le service Web répond avec un code d'état HTTP 401?
Vous devez implémenter ResponseErrorHandler
afin d'intercepter le code de réponse, le corps et l'en-tête lorsque vous obtenez des codes de réponse non 2xx du service à l'aide du modèle de repos. Copiez toutes les informations dont vous avez besoin, joignez-les à votre exception personnalisée et jetez-les afin de pouvoir les saisir dans votre 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;
}
}
Maintenant, ce que vous devez faire dans votre test est, définissez ce ResponseErrorHandler dans RestTemplate comme,
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]"));
}
Comme alternative à la solution présentée par nilesh, vous pouvez également utiliser la classe Spring DefaultResponseErrorHandler. Vous devez également remplacer sa méthode hasError (HttpStatus) afin qu'il ne lève pas d'exception sur les résultats non réussis.
restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
protected boolean hasError(HttpStatus statusCode) {
return false;
}});
Dans mon service de repos, j'attrape HttpStatusCodeException
au lieu de Exception
car HttpStatusCodeException
a une méthode pour obtenir le code d'état
catch(HttpStatusCodeException e) {
log.debug("Status Code", e.getStatusCode());
}
Vous pouvez utiliser Spring-test. C'est beaucoup plus simple:
@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()));
}
}
Depuis Spring 4.3, il existe un RestClientResponseException
qui contient les données de réponse HTTP réelles, telles que le code d'état, le corps de la réponse et les en-têtes. Et vous pouvez l'attraper.