Teste uma API REST com Java
1. Visão geral
Este tutorial se concentra nos princípios básicos e na mecânica detesting a REST API with live Integration Tests (com uma carga útil JSON).
# # O objetivo principal é fornecer uma introdução para testar a exatidão básica da API - e usaremos a versão mais recente doGitHub REST API para os exemplos.
Para um aplicativo interno, esse tipo de teste geralmente é executado como uma etapa final de um processo de Integração Contínua, consumindo a API REST depois que ela já foi implementada.
Ao testar um recurso REST, geralmente existem algumas responsabilidades ortogonais em que os testes devem se concentrar:
-
o HTTPresponse code
-
outro HTTPheaders na resposta
-
opayload (JSON, XML)
Each test should only focus on a single responsibility and include a single assertion. Focar em uma separação clara sempre traz benefícios, mas ao fazer esse tipo de teste de caixa preta é ainda mais importante, pois a tendência geral é escrever cenários de teste complexos no início.
Outro aspecto importante dos testes de integração é a aderência aoSingle Level of Abstraction Principle - a lógica dentro de um teste deve ser escrita em um alto nível. Detalhes como criar a solicitação, enviar a solicitação HTTP para o servidor, lidar com E / S etc. não devem ser feitos em linha, mas por meio de métodos utilitários.
Leitura adicional:
Teste de integração no Spring
Um guia rápido para escrever testes de integração para um aplicativo Web Spring.
Testando no Spring Boot
Aprenda como o Spring Boot suporta testes, para escrever testes de unidade com eficiência.
Um Guia para Garantia de REST
Explore os conceitos básicos da REST-assegurada - uma biblioteca que simplifica o teste e a validação das APIs REST.
2. Testando o código de status
@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
throws ClientProtocolException, IOException {
// Given
String name = RandomStringUtils.randomAlphabetic( 8 );
HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
// When
HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );
// Then
assertThat(
httpResponse.getStatusLine().getStatusCode(),
equalTo(HttpStatus.SC_NOT_FOUND));
}
Este é um teste bastante simples -it verifies that a basic happy path is working, sem adicionar muita complexidade ao conjunto de testes.
Se, por qualquer motivo, falhar, não será necessário procurar outro teste para este URL até que isso seja corrigido.
3. Testando o tipo de mídia
@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
throws ClientProtocolException, IOException {
// Given
String jsonMimeType = "application/json";
HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
// When
HttpResponse response = HttpClientBuilder.create().build().execute( request );
// Then
String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
assertEquals( jsonMimeType, mimeType );
}
Isso garante que a resposta realmente contenha dados JSON.
Como você deve ter notado,we’re following a logical progression of tests - primeiro o código de status de resposta (para garantir que a solicitação estava OK), depois o tipo de mídia da resposta e apenas no próximo teste veremos a carga real JSON.
4. Testando o Payload JSON
@Test
public void
givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
throws ClientProtocolException, IOException {
// Given
HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
// When
HttpResponse response = HttpClientBuilder.create().build().execute( request );
// Then
GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
response, GitHubUser.class);
assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}
Nesse caso, eu sei que a representação padrão dos recursos do GitHub é JSON, mas normalmente, o cabeçalho `++`Content-Type da resposta deve ser testado junto com o cabeçalhoAccept da solicitação - o cliente pergunta para um determinado tipo de representação viaAccept, que o servidor deve respeitar.
5. Utilitários para teste
Usaremos o Jackson 2 para remover a separação da JSON String bruta em uma Entidade Java segura para tipos:
public class GitHubUser {
private String login;
// standard getters and setters
}
Estamos usando apenas um utilitário simples para manter os testes limpos, legíveis e com um alto nível de abstração:
public static T retrieveResourceFromResponse(HttpResponse response, Class clazz)
throws IOException {
String jsonFromResponse = EntityUtils.toString(response.getEntity());
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue(jsonFromResponse, clazz);
}
Observe queJackson is ignoring unknown properties que a API do GitHub está enviando nosso caminho - isso é simplesmente porque a representação de um recurso do usuário no GitHub fica muito complexa - e não precisamos de nenhuma dessas informações aqui.
6. Dependências
Os utilitários e testes utilizam as seguintes bibliotecas, todas disponíveis no Maven central:
-
Hamcrest (opcional)
7. Conclusão
Essa é apenas uma parte do que deve ser o conjunto completo de testes de integração. Os testes se concentram emensuring basic correctness for the REST API, sem entrar em cenários mais complexos,
Por exemplo, o seguinte não é coberto: Detectabilidade da API, consumo de diferentes representações para o mesmo Recurso, etc.
[.iframe-fluido] ##
A implementação de todos esses exemplos e trechos de código pode ser encontradaover on Github - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.