Test en REST API med Java

1. Oversigt

Denne vejledning fokuserer på de grundlæggende principper og mekanik test af en REST API med live integrationstests (med en JSON-nyttelast).

Hovedmålet er at give en introduktion til at teste API'ens grundlæggende korrekthed - og vi bruger den nyeste version af GitHub REST API til eksemplerne.

For en intern applikation kører denne form for test normalt som et sent trin i en kontinuerlig integrationsproces, hvor REST API forbruges, efter at den allerede er blevet implementeret.

Når du tester en REST-ressource, er der normalt et par ortogonale ansvarsområder, som testene skal fokusere på:

  • HTTP svarkode
  • anden HTTP overskrifter i svaret
  • det nyttelast (JSON, XML)

Hver test bør kun fokusere på et enkelt ansvar og omfatte en enkelt påstand. At fokusere på en klar adskillelse har altid fordele, men når man udfører denne form for sort boks, er test endnu vigtigere, da den generelle tendens er at skrive komplekse testscenarier i starten.

Et andet vigtigt aspekt af integrationstestene er overholdelse af Enkelt abstraktionsniveau - logikken i en test skal skrives på et højt niveau. Detaljer som oprettelse af anmodningen, afsendelse af HTTP-anmodning til serveren, håndtering af IO osv. Bør ikke ske inline men via hjælpemetoder.

2. Test af statuskoden

@Test offentligt ugyldigt givetUserDoesNotExists_whUserInfoIsRetrieved_then404IsReceived () kaster ClientProtocolException, IOException {// Gitt strengnavn = RandomStringUtils.randomAlphabetic (8); HttpUriRequest anmodning = ny HttpGet ("//api.github.com/users/" + navn); // Når HttpResponse httpResponse = HttpClientBuilder.create (). Build (). Execute (anmodning); // Derefter hævder, at (httpResponse.getStatusLine (). GetStatusCode (), equalTo (HttpStatus.SC_NOT_FOUND)); }

Dette er en ret simpel test - det bekræfter, at en grundlæggende lykkelig sti fungereruden at tilføje for meget kompleksitet til testpakken.

Hvis det af en eller anden grund mislykkes, er der ingen grund til at se på nogen anden test for denne URL, før dette er rettet.

3. Test af medietypen

@Test offentlig ugyldighed givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson () kaster ClientProtocolException, IOException {// givet streng jsonMimeType = "applikation / json"; HttpUriRequest anmodning = ny HttpGet ("//api.github.com/users/eugenp"); // Når HttpResponse respons = HttpClientBuilder.create (). Build (). Execute (anmodning); // Derefter String mimeType = ContentType.getOrDefault (respons.getEntity ()). GetMimeType (); assertEquals (jsonMimeType, mimeType); }

Dette sikrer, at svaret faktisk indeholder JSON-data.

Som du måske har bemærket, vi følger en logisk progression af tests - først svarstatuskoden (for at sikre, at anmodningen var OK), derefter medietypen for svaret, og kun i den næste test ser vi på den faktiske JSON-nyttelast.

4. Test af JSON-nyttelasten

@Test offentligt ugyldigt givetUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect () kaster ClientProtocolException, IOException {// givet HttpUriRequest anmodning = ny HttpGet ("//api.github.com/users/eugenp"); // Når HttpResponse respons = HttpClientBuilder.create (). Build (). Execute (anmodning); // Derefter GitHubUser ressource = RetrieveUtil.retrieveResourceFromResponse (svar, GitHubUser.class); assertThat ("eugenp", Matchers.is (resource.getLogin ())); }

I dette tilfælde ved jeg, at standardrepræsentationen af ​​GitHub-ressourcer er JSON, men normalt er Indholdstype header af svaret skal testes sammen med Acceptere overskrift på anmodningen - klienten beder om en bestemt type repræsentation via Acceptere, som serveren skal ære.

5. Hjælpeprogrammer til testning

Vi skal bruge Jackson 2 til at afmontere den rå JSON-streng i en typesikker Java-enhed:

offentlig klasse GitHubUser {privat String login; // standard getters og setter}

Vi bruger kun et simpelt værktøj til at holde testene rene, læsbare og på et højt abstraktionsniveau:

offentlig statisk T retrieveResourceFromResponse (HttpResponse respons, Class clazz) kaster IOException {String jsonFromResponse = EntityUtils.toString (response.getEntity ()); ObjectMapper mapper = ny ObjectMapper () .configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return mapper.readValue (jsonFromResponse, clazz); }

Bemærk, at Jackson ignorerer ukendte egenskaber, som GitHub API sender vores vej - det er simpelthen fordi repræsentationen af ​​en brugerressource på GitHub bliver ret kompleks - og vi har ikke brug for nogen af ​​disse oplysninger her.

6. Afhængigheder

Hjælpeprogrammerne og testene bruger følgende biblioteker, alle tilgængelige i Maven central:

  • HttpClient
  • Jackson 2
  • Hamcrest (valgfri)

7. Konklusion

Dette er kun en del af, hvad den komplette integrationstestsuite skal være. Testene fokuserer på sikre grundlæggende korrekthed for REST APIuden at gå ind i mere komplekse scenarier,

F.eks. Er følgende ikke omfattet: API's opdagelighed, forbrug af forskellige repræsentationer for den samme ressource osv.

Implementeringen af ​​alle disse eksempler og kodestykker kan findes på Github - dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.


$config[zx-auto] not found$config[zx-overlay] not found