En guide til REST-sikret

Jackson Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Introduktion

REST-sikret var designet til at forenkle test og validering af REST API'er og er stærkt påvirket af testteknikker, der bruges i dynamiske sprog som Ruby og Groovy.

Biblioteket har solid understøttelse af HTTP, der naturligvis starter med verbene og standard HTTP-operationer, men også går langt ud over disse grundlæggende.

I denne vejledning skal vi udforsk REST-forsikret og vi vil bruge Hamcrest til at gøre påstand. Hvis du ikke allerede er fortrolig med Hamcrest, skal du først pusse op med vejledningen: Test med Hamcrest.

For at lære om mere avancerede brugstilfælde af REST-forsikret, se vores andre artikler:

  • ROL-forsikret med Groovy
  • JSON-skemavalidering med REST-sikret
  • Parametre, overskrifter og cookies med REST-sikret

Lad os nu dykke ind med et simpelt eksempel.

2. Simpel eksempel test

Lad os inden vores start sikre os, at vores tests har følgende statiske import:

io.restassured.RestAssured. * io.restassured.matcher.RestAssuredMatchers. * org.hamcrest.Matchers. *

Vi har brug for det for at holde testene enkle og have nem adgang til de vigtigste API'er.

Lad os komme i gang med det enkle eksempel - et grundlæggende væddemålssystem, der udsætter nogle data for spil:

{"id": "390", "data": {"leagueId": 35, "homeTeam": "Norway", "visitingTeam": "England",}, "odds": [{"price": "1.30 "," name ":" 1 "}, {" price ":" 5.25 "," name ":" X "}]}

Lad os sige, at dette er JSON-svaret fra at ramme den lokalt implementerede API - // localhost: 8080 / events? id = 390. :

Lad os nu bruge REST-sikret til at verificere nogle interessante funktioner i svaret JSON:

@Test offentlig ugyldighed givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect () {get ("/ events? Id = 390"). Derefter (). StatusCode (200) .assertThat () .body ("data.leagueId", equalTo (35)); }

Så hvad vi gjorde her er - vi bekræftede, at et opkald til slutpunktet / begivenheder? id = 390 svarer med en krop, der indeholder en JSON String hvis leagueId af data objektet er 35.

Lad os se på et mere interessant eksempel. Lad os sige, at du gerne vil kontrollere, at odds array har optegnelser med priser 1.30 og 5.25:

@Test offentligt ugyldigt givetUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect () {get ("/ events? Id = 390"). Derefter (). AssertThat () .body ("odds.price", hasItems ("1.30", "5.25")); }

3. REST-sikret opsætning

Hvis dit foretrukne afhængighedsværktøj er Maven, tilføjer vi følgende afhængighed i pom.xml fil:

 io.sikker forsikret 3.3.0 test 

Følg dette link for at få den nyeste version.

REST-forsikret drager fordel af Hamcrest-matchers magt til at udføre sine påstande, så vi skal også inkludere den afhængighed:

 org.hamcrest hamcrest-all 2.1 

Den seneste version vil altid være tilgængelig på dette link.

4. Anonym JSON-rodvalidering

Overvej en matrix, der består af primitive i stedet for objekter:

[1, 2, 3]

Dette kaldes en anonym JSON-rod, hvilket betyder, at den ikke har noget nøgleværdipar, alligevel er det stadig gyldige JSON-data.

Vi kan køre validering i et sådant scenario ved hjælp af $ symbol eller en tom streng (“”) som sti. Antag, at vi udsætter ovenstående service igennem // localhost: 8080 / json så kan vi validere det sådan med REST-forsikret:

når (). get ("/ json"). derefter (). body ("$", hasItems (1, 2, 3));

eller sådan:

når (). get ("/ json"). derefter (). body ("", hasItems (1, 2, 3));

5. Flyder og dobbelt

Når vi begynder at bruge REST-sikret til at teste vores REST-tjenester, er vi nødt til at forstå, at floating point-numre i JSON-svar kortlægges til primitiv type flyde.

Brugen af flyde typen kan ikke udskiftes med dobbelt som det er tilfældet for mange scenarier i java.

Eksempel på dette svar er:

{"odd": {"price": "1.30", "ck": 12.2, "name": "1"}}

antag, at vi kører følgende test på værdien af ck:

get ("/ odd"). derefter (). assertThat (). body ("odd.ck", equalTo (12.2));

Denne test mislykkes, selvom den værdi, vi tester, er lig med værdien i svaret. Dette skyldes, at vi sammenligner med a dobbelt snarere end til en flyde.

For at få det til at fungere skal vi eksplicit angive operanden til svarende til matcher metode som en flyde, ligesom:

get ("/ odd"). derefter (). assertThat (). body ("odd.ck", equalTo (12.2f));

6. Angivelse af anmodningsmetoden

Vi udfører typisk en anmodning ved at kalde en metode som f.eks få(), svarende til den anmodningsmetode, vi vil bruge.

Ud over, Vi kan også specificere HTTP-verbet ved hjælp af anmodning() metode:

@Test offentlig ugyldig nårRequestGet_thenOK () {når (). Anmodning ("GET", "/users/eugenp").then().statusCode(200); }

Eksemplet ovenfor svarer til brug få() direkte.

På samme måde kan vi sende HOVED, OPRET FORBINDELSE og MULIGHEDER anmodninger:

@Test offentlig ugyldig nårRequestHead_thenOK () {når (). Anmodning ("HEAD", "/users/eugenp").then().statusCode(200); }

STOLPE anmodning følger også en lignende syntaks, og vi kan specificere kroppen ved hjælp af med() og legeme() metoder.

Derfor at skabe et nyt Ulige ved at sende en STOLPE anmodning:

@Test offentlig ugyldig nårRequestedPost_thenCreated () {with (). Body (new Odd (5.25f, 1, 13.1f, "X")) .when () .request ("POST", "/ odds / new") .then () .statusCode (201); }

Det Ulige objekt sendt som legeme vil automatisk blive konverteret til JSON. Vi kan også videregive enhver Snor som vi vil sende som vores STOLPElegeme.

7. Konfiguration af standardværdier

Vi kan konfigurere mange standardværdier til testene:

@Før offentlig tomrumsopsætning () {RestAssured.baseURI = "//api.github.com"; RestAssured.port = 443; }

Her indstiller vi en base-URI og port til vores anmodninger. Udover disse kan vi også konfigurere basisstien, rodpat og godkendelse.

Bemærk: Vi kan også nulstille til standard REST-sikre standardindstillinger ved hjælp af:

RestAssured.reset ();

8. Mål responstid

Lad os se, hvordan vi kan måle svartiden ved hjælp af tid() og timeIn () metoder til Respons objekt:

@Test offentlig ugyldig nårMeasureResponseTime_thenOK () {Response response = RestAssured.get ("/ users / eugenp"); lang timeInMS = respons.tid (); lang timeInS = respons.timeIn (TimeUnit.SECONDS); assertEquals (timeInS, timeInMS / 1000); }

Noter det:

  • tid() bruges til at få svartid i millisekunder
  • timeIn () bruges til at få responstid i den specificerede tidsenhed

8.1. Bekræft svartid

Vi kan også validere svartiden - i millisekunder - ved hjælp af simpelt langMatcher:

@Test offentlig ugyldig nårValidateResponseTime_thenSuccess () {når (). Get ("/ brugere / eugenp"). Derefter (). Tid (lessThan (5000L)); }

Hvis vi vil validere svartiden i en anden tidsenhed, bruger vi tid() matcher med et sekund TimeUnit parameter:

@Test offentlig ugyldig nårValidateResponseTimeInSeconds_thenSuccess () {når (). Get ("/ brugere / eugenp"). Derefter (). Tid (lessThan (5L), TimeUnit.SECONDS); }

9. XML-responsbekræftelse

Ikke kun kan det validere et JSON-svar, det kan også validere XML.

Lad os antage, at vi fremsætter en anmodning til // localhost: 8080 / ansatte og vi får følgende svar:

  Jane Daisy f 

Vi kan kontrollere, at fornavn er Jane ligesom:

@Test offentligt ugyldigt givenUrl_whenXmlResponseValueTestsEqual_thenCorrect () {post ("/ workers"). Derefter (). AssertThat () .body ("medarbejder.medarbejder. Første navn", equalTo ("Jane")) }

Vi kan også kontrollere, at alle værdier matcher vores forventede værdier ved at kæde body matchers sammen på en sådan måde:

@Test offentligt ugyldigt givetUrl_whenMultipleXmlValuesTestEqual_thenCorrect () {post ("/ workers"). Derefter (). AssertThat () .body ("medarbejder.medarbejder.firstnavn", equalTo ("Jane")) .krop ("ansatte.medarbejder . efternavn ", equalTo (" Daisy ")) .body (" medarbejdere.medarbejder.sex ", equalTo (" f ")); }

Eller ved hjælp af stenografiversionen med variable argumenter:

@Test offentligt ugyldigt givetUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect () {post ("/ workers") .then (). AssertThat (). Body ("workers.employee.first-name", equalTo ("Jane"), "workers.employee.last- navn ", equalTo (" Daisy ")," ansatte.medarbejder.sex ", equalTo (" f ")); }

10. XPath til XML

Vi kan også kontrollere vores svar ved hjælp af XPath. Overvej eksemplet nedenfor, der udfører en matcher på fornavn:

@Test offentligt ugyldigt givenUrl_whenValidatesXmlUsingXpath_thenCorrect () {post ("/ workers"). Derefter (). AssertThat (). organ (hasXPath ("/ medarbejdere / medarbejder / fornavn", indeholderString ("Ja")); }

XPath accepterer også en alternativ måde at køre svarende til matcher:

@Test offentligt ugyldigt givetUrl_whenValidatesXmlUsingXpath2_thenCorrect () {post ("/ workers"). Derefter (). AssertThat () .body (hasXPath ("/ ansatte / medarbejder / fornavn [text () = 'Jane']")); }

11. Oplysninger om logningstest

11.1. Log anmodning detaljer

Lad os først se, hvordan man gør det log hele anmodningsoplysninger ved hjælp af log (). alle ():

@Test offentlig ugyldig nårLogRequest_thenOK () {given (). Log (). All () .when (). Get ("/ users / eugenp") .then (). StatusCode (200); }

Dette logger noget som dette:

Anmodningsmetode: GET Anmod om URI: //api.github.com:443/users/eugenp Proxy: Anmod om params: Forespørgselsparametre: Formparametre: Parametre for stier: Multiparts: Overskrifter: Accepter = * / * Cookies: Body: 

For kun at logge bestemte dele af anmodningen har vi log () metode i kombination med params (), body (), headers (), cookies (), metode (), path () f.eks log. (). params ().

Bemærk, at andre anvendte biblioteker eller filtre kan ændre, hvad der faktisk sendes til serveren, så dette bør kun bruges til at logge den oprindelige anmodningsspecifikation.

11.2. Log svar detaljer

På samme måde kan vi logge svardetaljerne.

I det følgende eksempel logger vi kun responsorganet:

@Test offentlig ugyldig nårLogResponse_thenOK () {når (). Get ("/ repos / eugenp / tutorials") .then (). Log (). Body (). StatusCode (200); }

Prøveoutput:

{"id": 9754983, "name": "tutorials", "full_name": "eugenp / tutorials", "private": false, "html_url": "//github.com/eugenp/tutorials", "description" : "The" REST With Spring \ "Course:", "fork": false, "size": 72371, "licens": {"key": "mit", "name": "MIT License", "spdx_id ":" MIT "," url ":" //api.github.com/licenses/mit "}, ...}

11.3. Logrespons, hvis tilstand opstod

Vi har også muligheden for kun at logge svaret, hvis der opstod en fejl, eller statuskoden matcher en given værdi:

@Test offentligt ugyldigt nårLogResponseIfErrorOccurred_thenSuccess () {når (). Get ("/ brugere / eugenp"). Derefter (). Log (). IfError (); når (). get ("/ users / eugenp") .then (). log (). ifStatusCodeIsEqualTo (500); når (). get ("/ users / eugenp") .then (). log (). ifStatusCodeMatches (greaterThan (200)); }

11.4. Log, hvis validering mislykkedes

Vi kan også kun logge både anmodning og svar, hvis vores validering mislykkedes:

@Test offentlig ugyldig nårLogOnlyIfValidationFailed_thenSuccess () {når (). Get ("/ brugere / eugenp") .dan (). Log (). IfValidationFails (). StatusCode (200); givet (). log (). ifValidationFails () .when (). get ("/ users / eugenp") .then (). statusCode (200); }

I dette eksempel vil vi validere, at statuskoden er 200. Kun hvis dette mislykkes, bliver anmodningen og svaret logget.

12. Konklusion

I denne vejledning har vi det udforskede den REST-sikrede ramme og kiggede på de vigtigste funktioner, som vi kan bruge til at teste vores RESTful-tjenester og validere deres svar.

Den fulde implementering af alle disse eksempler og kodestykker findes i det REST-sikrede GitHub-projekt.

Jackson bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

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