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.