Test een REST API met Java

1. Overzicht

Deze tutorial richt zich op de basisprincipes en mechanica van het testen van een REST API met live integratietests (met een JSON-payload).

Het belangrijkste doel is om een ​​inleiding te bieden voor het testen van de basiscorrectheid van de API - en we gaan de nieuwste versie van de GitHub REST API gebruiken voor de voorbeelden.

Voor een interne applicatie wordt dit soort testen meestal uitgevoerd als een late stap in een continu integratieproces, waarbij de REST API wordt gebruikt nadat deze al is geïmplementeerd.

Bij het testen van een REST-resource zijn er meestal een paar orthogonale verantwoordelijkheden waarop de tests zich moeten concentreren:

  • het HTTP Reactiecode
  • andere HTTP headers in de reactie
  • de laadvermogen (JSON, XML)

Elke test mag zich alleen richten op een enkele verantwoordelijkheid en een enkele bewering bevatten. Focussen op een duidelijke scheiding heeft altijd voordelen, maar bij dit soort black-box-testen is het zelfs nog belangrijker, aangezien de algemene tendens is om vanaf het allereerste begin complexe testscenario's te schrijven.

Een ander belangrijk aspect van de integratietests is de naleving van de Principe van enkel abstractieniveau - de logica binnen een test moet op een hoog niveau worden geschreven. Details zoals het maken van het verzoek, het verzenden van het HTTP-verzoek naar de server, het omgaan met IO, enz. Mogen niet inline worden gedaan, maar via hulpprogramma-methoden.

2. Testen van de statuscode

@Test openbare ongeldige gegevenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived () gooit ClientProtocolException, IOException {// Given String name = RandomStringUtils.randomAlphabetic (8); HttpUriRequest request = nieuwe HttpGet ("//api.github.com/users/" + naam); // Wanneer HttpResponse httpResponse = HttpClientBuilder.create (). Build (). Execute (verzoek); // Vervolgens assertThat (httpResponse.getStatusLine (). GetStatusCode (), equalTo (HttpStatus.SC_NOT_FOUND)); }

Dit is een vrij eenvoudige test - het bevestigt dat een fundamenteel gelukkig pad werkt, zonder al te veel complexiteit toe te voegen aan de testsuite.

Als het om welke reden dan ook mislukt, hoeft u niet naar een andere test voor deze URL te kijken totdat dit is opgelost.

3. Testen van het mediatype

@Test openbare ongeldig gegevenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson () gooit ClientProtocolException, IOException {// Gegeven String jsonMimeType = "application / json"; HttpUriRequest request = nieuwe HttpGet ("//api.github.com/users/eugenp"); // When HttpResponse response = HttpClientBuilder.create (). Build (). Execute (request); // Dan String mimeType = ContentType.getOrDefault (response.getEntity ()). GetMimeType (); assertEquals (jsonMimeType, mimeType); }

Dit zorgt ervoor dat de Response daadwerkelijk JSON-gegevens bevat.

Zoals je misschien hebt gemerkt, we volgen een logisch verloop van tests - eerst de responsstatuscode (om er zeker van te zijn dat het verzoek in orde was), dan het mediatype van de respons, en pas in de volgende test zullen we kijken naar de werkelijke JSON-payload.

4. Testen van de JSON-payload

@Test openbare ongeldige gegevenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect () gooit ClientProtocolException, IOException {// Gegeven HttpUriRequest-verzoek = nieuwe HttpGet ("//api.github.com/users/eugenp"); // When HttpResponse response = HttpClientBuilder.create (). Build (). Execute (request); // Dan GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse (antwoord, GitHubUser.class); assertThat ("eugenp", Matchers.is (resource.getLogin ())); }

In dit geval weet ik dat de standaardweergave van GitHub-bronnen JSON is, maar meestal is de Inhoudstype header van het antwoord moet worden getest naast de Aanvaarden header van het verzoek - de klant vraagt ​​om een ​​bepaald type weergave via Aanvaarden, die de server zou moeten eren.

5. Hulpprogramma's voor testen

We gaan Jackson 2 gebruiken om de onbewerkte JSON-string ongedaan te maken in een typeveilige Java-entiteit:

openbare klasse GitHubUser {privé String-login; // standaard getters en setters}

We gebruiken alleen een eenvoudig hulpprogramma om de tests schoon, leesbaar en op een hoog abstractieniveau te houden:

openbare statische T retrieveResourceFromResponse (HttpResponse response, Class clazz) gooit IOException {String jsonFromResponse = EntityUtils.toString (response.getEntity ()); ObjectMapper mapper = nieuwe ObjectMapper () .configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return mapper.readValue (jsonFromResponse, clazz); }

Merk op dat Jackson onbekende eigenschappen negeert die de GitHub API onze kant op stuurt - dat is simpelweg omdat de weergave van een gebruikersresource op GitHub behoorlijk complex wordt - en we hebben hier geen van die informatie nodig.

6. Afhankelijkheden

De hulpprogramma's en tests maken gebruik van de volgende bibliotheken, allemaal beschikbaar in Maven Central:

  • HttpClient
  • Jackson 2
  • Hamcrest (optioneel)

7. Conclusie

Dit is slechts een deel van wat de complete integratietestsuite zou moeten zijn. De tests richten zich op zorgen voor basiscorrectheid voor de REST API, zonder in te gaan op complexere scenario's,

Het volgende is bijvoorbeeld niet gedekt: vindbaarheid van de API, gebruik van verschillende weergaven voor dezelfde bron, enz.

De implementatie van al deze voorbeelden en codefragmenten is te vinden op Github - dit is een op Maven gebaseerd project, dus het moet gemakkelijk te importeren en uit te voeren zijn zoals het is.