Test en REST API med Java

1. Oversikt

Denne opplæringen fokuserer på de grunnleggende prinsippene og mekanikken til teste et REST API med live integrasjonstester (med en JSON-nyttelast).

Hovedmålet er å gi en introduksjon til å teste den grunnleggende riktigheten av API - og vi skal bruke den nyeste versjonen av GitHub REST API for eksemplene.

For en intern applikasjon vil denne typen testing vanligvis kjøre som et sent trinn i en kontinuerlig integrasjonsprosess, og forbruker REST API etter at den allerede er distribuert.

Når du tester en REST-ressurs, er det vanligvis et par ortogonale ansvar testene bør fokusere på:

  • HTTP svarskode
  • annen HTTP topptekster i svaret
  • de nyttelast (JSON, XML)

Hver test skal bare fokusere på et enkelt ansvar og inkludere en enkelt påstand. Å fokusere på en klar separasjon har alltid fordeler, men når du gjør denne typen black box-testing, er det enda viktigere, siden den generelle tendensen er å skrive komplekse testscenarier helt i starten.

Et annet viktig aspekt ved integrasjonstestene er overholdelse av Enkelt nivå for abstraksjonsprinsipp - logikken i en test skal skrives på høyt nivå. Detaljer som å opprette forespørselen, sende HTTP-forespørselen til serveren, håndtere IO osv., Bør ikke gjøres integrert, men via verktøymetoder.

2. Testing av statuskoden

@Test offentlig ugyldighet gittUserDoesNotExists_whUnderInfoIsRetrieved_then404IsReceived () kaster ClientProtocolException, IOException {// Gitt strengnavn = RandomStringUtils.randomAlphabetic (8); HttpUriRequest forespørsel = ny HttpGet ("//api.github.com/users/" + navn); // Når HttpResponse httpResponse = HttpClientBuilder.create (). Build (). Execute (forespørsel); // Så hevder det (httpResponse.getStatusLine (). GetStatusCode (), equalTo (HttpStatus.SC_NOT_FOUND)); }

Dette er en ganske enkel test - det bekrefter at en grunnleggende lykkelig vei fungerer, uten å legge for mye kompleksitet til testpakken.

Hvis det av en eller annen grunn mislykkes, er det ikke nødvendig å se på noen annen test for denne URL-en før denne er løst.

3. Test av medietypen

@Test offentlig ugyldig givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson () kaster ClientProtocolException, IOException {// Gitt streng jsonMimeType = "application / json"; HttpUriRequest-forespørsel = ny HttpGet ("//api.github.com/users/eugenp"); // Når HttpResponse respons = HttpClientBuilder.create (). Build (). Execute (forespørsel); // Deretter String mimeType = ContentType.getOrDefault (respons.getEntity ()). GetMimeType (); assertEquals (jsonMimeType, mimeType); }

Dette sikrer at svaret faktisk inneholder JSON-data.

Som du kanskje har lagt merke til, vi følger en logisk progresjon av tester - først svarstatuskoden (for å sikre at forespørselen var OK), deretter mediatypen for svaret, og bare i neste test ser vi på den faktiske JSON-nyttelasten.

4. Testing av JSON nyttelast

@Test offentlig ugyldig gittUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect () kaster ClientProtocolException, IOException {// Gitt HttpUriRequest-forespørsel = ny HttpGet ("//api.github.com/users/eugenp"); // Når HttpResponse respons = HttpClientBuilder.create (). Build (). Execute (forespørsel); // Deretter GitHubUser ressurs = RetrieveUtil.retrieveResourceFromResponse (respons, GitHubUser.class); assertThat ("eugenp", Matchers.is (resource.getLogin ())); }

I dette tilfellet vet jeg at standardrepresentasjonen av GitHub-ressurser er JSON, men vanligvis er Innholdstype header of the response bør testes ved siden av Aksepterer overskrift på forespørselen - klienten ber om en bestemt type representasjon via Aksepterer, som serveren skal respektere.

5. Verktøy for testing

Vi skal bruke Jackson 2 til å oppheve den rå JSON-strengen i en typesikker Java-enhet:

offentlig klasse GitHubUser {privat strenginnlogging; // standard getters og setters}

Vi bruker bare et enkelt verktøy for å holde testene rene, lesbare og på et høyt abstraksjonsnivå:

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

Legg merke til at Jackson ignorerer ukjente egenskaper som GitHub API sender vår vei - det er ganske enkelt fordi representasjonen av en brukerressurs på GitHub blir ganske kompleks - og vi trenger ikke noe av denne informasjonen her.

6. Avhengigheter

Verktøyene og testene bruker følgende biblioteker, alle tilgjengelige i Maven Central:

  • HttpClient
  • Jackson 2
  • Hamcrest (valgfritt)

7. Konklusjon

Dette er bare en del av hva den komplette integrasjonstestpakken skal være. Testene fokuserer på sikre grunnleggende korrekthet for REST APIuten å gå inn i mer komplekse scenarier,

For eksempel dekkes ikke følgende: Oppdagbarhet av API, forbruk av forskjellige representasjoner for samme ressurs, etc.

Implementeringen av alle disse eksemplene og kodebitene finner du på Github - dette er et Maven-basert prosjekt, så det skal være enkelt å importere og kjøre som det er.


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