Forbrukerdrevne kontrakter med pakt

1. Oversikt

I denne raske artikkelen ser vi på konseptet forbrukerdrevne kontrakter.

Vi skal teste integrering med en ekstern REST-tjeneste gjennom en kontrakt som vi definerer ved hjelp av Pakt bibliotek. Denne kontrakten kan defineres av klienten, deretter hentes av leverandøren og brukes til utvikling av tjenestene.

Vi vil også lage tester basert på kontrakten for både klient- og leverandørapplikasjoner.

2. Hva er? Pakt?

Ved hjelp av Pakt, vi kan definere forbrukernes forventninger til en gitt leverandør (som kan være en HTTP REST-tjeneste) i form av en kontrakt (derav navnet på biblioteket).

Vi skal sette opp denne kontrakten ved hjelp av DSL levert av Pakt. Når vi er definert, kan vi teste interaksjoner mellom forbrukere og leverandøren ved hjelp av mock-tjenesten som er opprettet basert på den definerte kontrakten. Vi vil også teste tjenesten mot kontrakten ved å bruke en mock-klient.

3. Maven avhengighet

For å komme i gang må vi legge til Maven-avhengighet til pakt-jvm-forbruker-junit_2.11 bibliotek:

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

4. Definere en kontrakt

Når vi ønsker å lage en test ved hjelp av Pakt, først må vi definere en @Regel som vil bli brukt i testen vår:

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

Vi sender leverandørnavnet, verten og porten som server-spotten (som er opprettet fra kontrakten) startes.

La oss si at tjenesten har definert kontrakten for to HTTP-metoder som den kan håndtere.

Den første metoden er en GET-forespørsel som returnerer JSON med to felt. Når forespørselen lykkes, returnerer den en 200 HTTP-responskode og Content-Type topptekst til JSON.

La oss definere en slik kontrakt ved hjelp av Pakt.

Vi må bruke @Pakt kommentar og gi forbrukernavnet som kontrakten er definert for. Inne i den merkede metoden kan vi definere GET-kontrakten vår:

@Pact (forbruker = "test_forbruker") offentlig RequestResponsePact createPact (PactDslWithProvider-byggmester) {Map headers = new HashMap (); headers.put ("Content-Type", "application / json"); returbygger .given ("test GET") .uponReceiving ("GET REQUEST") .path ("/ pact") .metode ("GET") .willRespondWith () .status (200) .headers (headers) .body ( "{\" tilstand \ ": sant, \" navn \ ": \" tom \ "}") (...)}

Bruker Pakt DSL definerer vi at vi for en gitt GET-forespørsel ønsker å returnere et 200-svar med spesifikke overskrifter og kropp.

Den andre delen av kontrakten vår er POST-metoden. Når klienten sender en POST-forespørsel til banen /pakt med en skikkelig JSON-kropp returnerer den en 201 HTTP-responskode.

La oss definere en slik kontrakt med Pakt:

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

Merk at vi må ringe toPact () metode på slutten av kontrakten for å returnere en forekomst av RequestResponsePact.

4.1. Resulterende paktartefakt

Som standard blir Pact-filer generert i mål / pakter mappe. For å tilpasse denne banen kan vi konfigurere maven-surefire-plugin:

 org.apache.maven.plugins maven-surefire-plugin target / mypacts ... 

Maven-bygningen genererer en fil som heter test_consumer-test_provider.json i mål / mypacts mappe som inneholder strukturen til forespørslene og svarene:

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

5. Testing av klient og leverandør ved bruk av kontrakten

Nå som vi har kontrakten vår, kan vi bruke til å lage tester mot den for både klienten og leverandøren.

Hver av disse testene vil bruke en mock av motstykket som er basert på kontrakten, noe som betyr:

  • klienten vil bruke en mock-leverandør
  • leverandøren vil bruke en mock-klient

Effektivt blir testene gjort mot kontrakten.

5.1. Testing av klienten

Når vi har definert kontrakten, kan vi teste interaksjoner med tjenesten som blir opprettet basert på den kontrakten. Vi kan lage normal JUnit-test, men vi må huske å sette @PactVerification kommentar i begynnelsen av testen.

La oss skrive en test for GET-forespørselen:

@Test @PactVerification () public void givenGet_whenSendRequest_shouldReturn200WithProperHeaderAndBody () {// when ResponseEntity response = new RestTemplate () .getForEntity (mockProvider.getUrl () + "/ pact", String.class); // deretter assertThat (respons.getStatusCode (). verdi ()). erEqualTo (200); assertThat (respons.getHeaders (). get ("Content-Type"). inneholder ("application / json")). isTrue (); assertThat (respons.getBody ()). inneholder ("betingelse", "sant", "navn", "tom"); }

De @PactVerification merknader tar seg av å starte HTTP-tjenesten. I testen trenger vi bare å sende GET-forespørselen og hevde at svaret vårt er i samsvar med kontrakten.

La oss også legge til testen for POST-metoden:

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); // deretter assertThat (postResponse.getStatusCode (). verdi ()). er EqualTo (201);

Som vi kan se, er svarskoden for POST-forespørselen lik 201 - nøyaktig slik den ble definert i Pakt kontrakt.

Mens vi brukte @PactVerification () kommentar, den Pakt biblioteket starter webserveren basert på den tidligere definerte kontrakten før testsaken vår.

5.2. Test av leverandøren

Det andre trinnet i kontraktsbekreftelsen er å lage en test for leverandøren som bruker en mock-klient basert på kontrakten.

Vår leverandørimplementering vil være drevet av denne kontrakten på TDD-måte.

For vårt eksempel bruker vi en Spring Boot REST API.

Først, for å lage vår JUnit-test, må vi legge til avhengigheten pact-jvm-provider-junit_2.11:

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

Dette lar oss lage en JUnit-test ved hjelp av PactRunner og spesifisere leverandørnavnet og plasseringen av paktartefakten:

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

For at denne konfigurasjonen skal fungere, må vi plassere test_consumer-test_provider.json filen i pakter mappe i REST-tjenesteprosjektet vårt.

Deretter definerer vi målet som skal brukes til å verifisere interaksjonene i kontrakten og starte Spring Boot-appen før du kjører testene:

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

Til slutt spesifiserer vi tilstandene i kontrakten vi vil teste:

@State ("test GET") offentlig ugyldig toGetState () {} @State ("test POST") offentlig ugyldig til PostState () {}

Å kjøre denne JUnit-klassen vil utføre to tester for de to GET- og POST-forespørslene. La oss ta en titt på loggen:

Verifisere en pakt mellom test_forbruker og testleverandør Gitt test GET GET REQUEST returnerer et svar som har statuskode 200 (OK) inkluderer overskrifter "Content-Type" med verdien "application / json" (OK) har en samsvarende kropp (OK) Bekreftelse av en pakt mellom testforbruker og testleverandør Gitt test POST POST REQUEST returnerer et svar som har statuskode 201 (OK) har en matchende kropp (OK)

Merk at vi ikke har tatt med koden for å opprette en REST-tjeneste her. Full service og test finner du i GitHub-prosjektet.

6. Konklusjon

I denne raske opplæringen så vi på forbrukerdrevne kontrakter.

Vi opprettet en kontrakt ved hjelp av Pakt bibliotek. Når vi hadde definert kontrakten, klarte vi å teste klienten og tjenesten mot kontrakten og hevde at de overholder spesifikasjonen.

Implementeringen av alle disse eksemplene og kodebitene finnes i GitHub-prosjektet - dette er et Maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.


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