Forbrugerdrevne kontrakter med pagt

1. Oversigt

I denne hurtige artikel vil vi se på begrebet forbrugerdrevne kontrakter.

Vi tester integration med en ekstern REST-tjeneste gennem en kontrakt, som vi definerer ved hjælp af Pagt bibliotek. Denne kontrakt kan defineres af klienten, derefter afhentes af udbyderen og bruges til udvikling af dens tjenester.

Vi opretter også tests baseret på kontrakten for både klient- og udbyderapplikationer.

2. Hvad er? Pagt?

Ved brug af Pagt, Vi kan definere forbrugernes forventninger til en given udbyder (det kan være en HTTP REST-tjeneste) i form af en kontrakt (deraf navnet på biblioteket).

Vi opretter denne kontrakt ved hjælp af DSL leveret af Pagt. Når vi er defineret, kan vi teste interaktioner mellem forbrugere og udbyderen ved hjælp af den mock-service, der oprettes baseret på den definerede kontrakt. Vi tester også tjenesten mod kontrakten ved hjælp af en mock-klient.

3. Maven-afhængighed

For at komme i gang skal vi tilføje Maven-afhængighed til pact-jvm-forbruger-junit_2.11 bibliotek:

 au.com.dius pact-jvm-forbruger-junit_2.11 3.5.0 test 

4. Definition af en kontrakt

Når vi vil oprette en test ved hjælp af Pagt, først skal vi definere en @Herske der vil blive brugt i vores test:

@Rule public PactProviderRuleMk2 mockProvider = ny PactProviderRuleMk2 ("test_provider", "localhost", 8080, dette);

Vi videregiver udbyderens navn, vært og port, som servermocken (som oprettes ud fra kontrakten) startes på.

Lad os sige, at tjenesten har defineret kontrakten for to HTTP-metoder, som den kan håndtere.

Den første metode er en GET-anmodning, der returnerer JSON med to felter. Når anmodningen lykkes, returnerer den en 200 HTTP-svarskode og Content-Type header til JSON.

Lad os definere en sådan kontrakt ved hjælp af Pagt.

Vi er nødt til at bruge @Pagt kommentar og videregive det forbrugernavn, som kontrakten er defineret for. Inde i den kommenterede metode kan vi definere vores GET-kontrakt:

@Pact (forbruger = "test_forbruger") offentlig RequestResponsePact createPact (PactDslWithProvider builder) {Map headers = new HashMap (); headers.put ("Content-Type", "application / json"); return builder .given ("test GET") .uponReceiving ("GET REQUEST") .path ("/ pact") .metode ("GET") .willRespondWith () .status (200) .headers (headers) .body ( "{\" betingelse \ ": sandt, \" navn \ ": \" tom \ "}") (...)}

Bruger Pagt DSL definerer vi, at vi for en given GET-anmodning vil returnere et 200-svar med specifikke overskrifter og body.

Den anden del af vores kontrakt er POST-metoden. Når klienten sender en POST-anmodning til stien /pagt med et ordentligt JSON-organ returnerer det en 201 HTTP-svarskode.

Lad os definere en sådan kontrakt med Pagt:

(...) .given ("test POST") .uponReceiving ("POST REQUEST") .metode ("POST"). headers (headers) .body ("{\" name \ ": \" Michael \ "} ") .sti (" / pagt ") .willRespondWith () .status (201) .toPact ();

Bemærk, at vi skal ringe til toPact () metode i slutningen af ​​kontrakten for at returnere en instans af RequestResponsePact.

4.1. Resulterende pagtartefakt

Som standard genereres paktfiler i mål / pakter folder. For at tilpasse denne sti kan vi konfigurere maven-surefire-plugin:

 org.apache.maven.plugins maven-surefire-plugin mål / mypacts ... 

Maven-build genererer en fil, der kaldes test_consumer-test_provider.json i target / mypacts mappe, der indeholder strukturen på anmodningerne og svarene:

{"provider": {"name": "test_provider"}, "consumer": {"name": "test_consumer"}, "interactions": [{"description": "FÅ ANMODNING", "anmodning": {" metode ":" GET "," path ":" / "}," response ": {" status ": 200," headers ": {" Content-Type ":" application / json "}," body ": { "condition": true, "name": "tom"}}, "providerStates": [{"name": "test GET"}]}, {"description": "POST ANMODNING", ...}], "metadata": {"pact-specification": {"version": "3.0.0"}, "pact-jvm": {"version": "3.5.0"}}}

5. Test af klienten og udbyderen ved hjælp af kontrakten

Nu hvor vi har vores kontrakt, kan vi bruge til at oprette tests mod den for både klienten og udbyderen.

Hver af disse tests bruger en mock af sin modstykke, der er baseret på kontrakten, hvilket betyder:

  • klienten bruger en mock-udbyder
  • udbyderen bruger en mock-klient

Testene udføres effektivt mod kontrakten.

5.1. Test af klienten

Når vi har defineret kontrakten, kan vi teste interaktioner med den service, der oprettes på baggrund af den pågældende kontrakt. Vi kan oprette normal JUnit-test, men vi skal huske at sætte @PactVerification kommentar i begyndelsen af ​​testen.

Lad os skrive en test til GET-anmodningen:

@Test @PactVerification () public void givenGet_whenSendRequest_shouldReturn200WithProperHeaderAndBody () {// when ResponseEntity response = new RestTemplate () .getForEntity (mockProvider.getUrl () + "/ pact", String.class); // derefter assertThat (respons.getStatusCode (). værdi ()). er EqualTo (200); assertThat (respons.getHeaders (). get ("Content-Type"). indeholder ("application / json")). isTrue (); assertThat (respons.getBody ()). indeholder ("betingelse", "sand", "navn", "tom"); }

Det @PactVerification annotation tager sig af start af HTTP-tjenesten. I testen behøver vi kun at sende GET-anmodningen og hævde, at vores svar overholder kontrakten.

Lad os også tilføje testen til POST-metodeopkaldet:

HttpHeaders httpHeaders = nye HttpHeaders (); httpHeaders.setContentType (MediaType.APPLICATION_JSON); String jsonBody = "{\" name \ ": \" Michael \ "}"; // når ResponseEntity postResponse = ny RestTemplate () .exchange (mockProvider.getUrl () + "/ create", HttpMethod.POST, ny HttpEntity (jsonBody, httpHeaders), String.class); // derefter assertThat (postResponse.getStatusCode (). værdi ()). er EqualTo (201);

Som vi kan se, er svarkoden for POST-anmodningen lig med 201 - nøjagtigt som den blev defineret i Pagt kontrakt.

Da vi brugte @PactVerification () kommentar, den Pagt biblioteket starter webserveren på baggrund af den tidligere definerede kontrakt før vores testsag.

5.2. Test af udbyderen

Det andet trin i vores kontraktbekræftelse er at oprette en test for udbyderen ved hjælp af en mock klient baseret på kontrakten.

Vores leverandørimplementering vil være drevet af denne kontrakt på TDD-måde.

I vores eksempel bruger vi en Spring Boot REST API.

Først for at oprette vores JUnit-test skal vi tilføje afhængigheden pact-jvm-provider-junit_2.11:

 au.com.dius pact-jvm-provider-junit_2.11 3.5.0 test 

Dette giver os mulighed for at oprette en JUnit-test ved hjælp af PactRunner og specificering af udbyderens navn og placeringen af ​​pagtartefakten:

@RunWith (PactRunner.class) @Provider ("test_provider") @PactFolder ("pacts") offentlig klasse PactProviderTest {// ...}

For at denne konfiguration skal fungere, skal vi placere test_consumer-test_provider.json fil i pakter mappe i vores REST-serviceprojekt.

Dernæst definerer vi det mål, der skal bruges til at verificere interaktionerne i kontrakten og starte Spring Boot-appen, før testene køres:

@TestTarget offentlig endelig Target target = new HttpTarget ("http", "localhost", 8082, "/ spring-rest"); privat statisk ConfigurableWebApplicationContext-applikation; @BeforeClass offentlig statisk ugyldig start () {application = (ConfigurableWebApplicationContext) SpringApplication.run (MainApplication.class); }

Endelig specificerer vi de stater i kontrakten, som vi vil teste:

@State ("test GET") offentlig ugyldighed tilGetState () {} @State ("test POST") offentlig ugyldighed til PostState () {}

At køre denne JUnit-klasse udfører to tests for de to GET- og POST-anmodninger. Lad os se på loggen:

Bekræftelse af en pagt mellem test_forbruger og testudbyder Givet test FÅ FÅ ANMODNING returnerer et svar, der har statuskode 200 (OK) inkluderer overskrifter "Indholdstype" med værdien "applikation / json" (OK) har et matchende organ (OK) Verificering af en pagt mellem testforbruger og testudbyder Givet test POST POST ANMODNING returnerer et svar, der har statuskode 201 (OK) har en matchende krop (OK)

Bemærk, at vi ikke har medtaget koden til oprettelse af en REST-tjeneste her. Den fulde service og test findes i GitHub-projektet.

6. Konklusion

I denne hurtige vejledning kiggede vi på forbrugerdrevne kontrakter.

Vi oprettede en kontrakt ved hjælp af Pagt bibliotek. Når vi først havde defineret kontrakten, kunne vi teste klienten og servicen mod kontrakten og hævde, at de overholdt specifikationen.

Implementeringen af ​​alle disse eksempler og kodestykker findes i GitHub-projektet - dette er et Maven-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