Potrošački ugovori s Pactom

1. Pregled

U ovom ćemo kratkom članku pogledati koncept potrošačkih ugovora.

Testirat ćemo integraciju s vanjskom uslugom REST putem ugovora koji definiramo pomoću Pakt knjižnica. Taj ugovor klijent može definirati, a zatim ga podići davatelj i koristiti za razvoj njegovih usluga.

Također ćemo stvoriti testove na temelju ugovora i za klijentske i za dobavljačke programe.

2. Što je Pakt?

Koristeći Pakt, možemo definirati očekivanja potrošača za određenog davatelja usluga (koji može biti HTTP REST usluga) u obliku ugovora (otuda i naziv knjižnice).

Ovaj ćemo ugovor postaviti pomoću DSL-a koji nam je pružio Pakt. Jednom definirani, možemo testirati interakciju između potrošača i davatelja usluga pomoću lažne usluge koja je stvorena na temelju definiranog ugovora. Također ćemo testirati uslugu na temelju ugovora pomoću lažnog klijenta.

3. Ovisnost Mavena

Za početak trebamo dodati Mavenovu ovisnost pakt-jvm-potrošač-junit_2.11 knjižnica:

 au.com.dius pakt-jvm-potrošač-junit_2.11 3.5.0 test 

4. Definiranje ugovora

Kada želimo stvoriti test pomoću Pakt, prvo moramo definirati a @Pravilo koji će se koristiti u našem testu:

@Rule public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2 ("test_provider", "localhost", 8080, this);

Prosljeđujemo ime davatelja usluge, hosta i priključka na kojima će se pokrenuti lažni poslužitelj (koji je stvoren iz ugovora).

Recimo da je usluga definirala ugovor za dvije HTTP metode s kojima se može nositi.

Prva metoda je GET zahtjev koji vraća JSON s dva polja. Kad zahtjev uspije, vraća kôd odgovora 200 HTTP i Content-Type zaglavlje za JSON.

Definirajmo takav ugovor pomoću Pakt.

Moramo koristiti @Pakt napomena i proslijediti ime potrošača za koje je ugovor definiran. Unutar anotirane metode možemo definirati naš GET ugovor:

@Pact (potrošač = "test_consumer") javni RequestResponsePact createPact (PactDslWithProvider builder) {Map headers = new HashMap (); headers.put ("Content-Type", "application / json"); return builder .dan ("test GET") .uponReceiving ("GET REQUEST") .path ("/ pact") .method ("GET") .willRespondWith () .status (200) .headers (headers) .body ( "{\" condition \ ": true, \" name \ ": \" tom \ "}") (...)}

Koristiti Pakt DSL definiramo da za zadani GET zahtjev želimo vratiti odgovor 200 s određenim zaglavljima i tijelom.

Drugi dio našeg ugovora je POST metoda. Kada klijent pošalje POST zahtjev na stazu /pakt s ispravnim JSON tijelom vraća 201 HTTP odgovorni kôd.

Definirajmo takav ugovor s Pakt:

(...) .dan ("test POST") .uponReeiving ("POST REQUEST") .method ("POST") .headers (headers) .body ("{\" name \ ": \" Michael \ "} ") .path (" / pact ") .willRespondWith () .status (201) .toPact ();

Imajte na umu da moramo nazvati toPact () metoda na kraju ugovora za vraćanje instance RequestResponsePact.

4.1. Rezultirajući artefakt Pakta

Prema zadanim postavkama, datoteke Pact generirat će se u meta / pakti mapu. Da bismo prilagodili ovaj put, možemo konfigurirati maven-surefire-plugin:

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

Izrada Maven generirat će datoteku pod nazivom test_consumer-test_provider.json u meta / moji pakti mapa koja sadrži strukturu zahtjeva i odgovora:

{"provider": {"name": "test_provider"}, "consumer": {"name": "test_consumer"}, "interakcije": [{"description": "GET REQUEST", "request": {" metoda ":" GET "," path ":" / "}," response ": {" status ": 200," headers ": {" Content-Type ":" application / json "}," body ": { "condition": true, "name": "tom"}}, "providerStates": [{"name": "test GET"}]}, {"description": "POŠALJI UPIT", ...}], "metapodaci": {"pact-specification": {"version": "3.0.0"}, "pact-jvm": {"version": "3.5.0"}}}

5. Testiranje klijenta i dobavljača korištenjem ugovora

Sad kad imamo ugovor, možemo ga stvoriti za klijenta i davatelja usluge.

Svaki od ovih testova koristit će lažni primjer svog kolege koji se temelji na ugovoru, što znači:

  • klijent će se poslužiti lažnim davateljem usluga
  • davatelj će koristiti lažni klijent

Učinkovito, testovi se rade prema ugovoru.

5.1. Testiranje klijenta

Nakon što definiramo ugovor, možemo testirati interakciju sa uslugom koja će se stvoriti na temelju tog ugovora. Možemo stvoriti uobičajeni JUnit test, ali moramo upamtiti da stavimo @PactVerification napomena na početku testa.

Napišimo test za GET zahtjev:

@Test @PactVerification () javna praznina givenGet_whenSendRequest_shouldReturn200WithProperHeaderAndBody () {// kada je ResponseEntity odgovor = novi RestTemplate () .getForEntity (mockProvider.getUrl () + "/ pact", String.class ", String.class", String.class ", String. // zatim assertThat (response.getStatusCode (). value ()). isEqualTo (200); assertThat (response.getHeaders (). get ("Content-Type"). contains ("application / json")). isTrue (); assertThat (response.getBody ()). contains ("condition", "true", "name", "tom"); }

The @PactVerification anotacija brine o pokretanju HTTP usluge. U testu trebamo samo poslati GET zahtjev i ustvrditi da je naš odgovor u skladu s ugovorom.

Dodajmo test i za poziv metode POST:

HttpHeaders httpHeaders = novi HttpHeaders (); httpHeaders.setContentType (MediaType.APPLICATION_JSON); Niz jsonBody = "{\" name \ ": \" Michael \ "}"; // kada je ResponseEntity postResponse = novi RestTemplate () .exchange (mockProvider.getUrl () + "/ create", HttpMethod.POST, novi HttpEntity (jsonBody, httpHeaders), String.class); // zatim assertThat (postResponse.getStatusCode (). value ()). isEqualTo (201);

Kao što vidimo, kod odgovora za POST zahtjev jednak je 201 - točno onako kako je definiran u Pakt ugovor.

Kao što smo koristili @PactVerification () napomena, Pakt knjižnica pokreće web poslužitelj na temelju prethodno definiranog ugovora prije našeg testnog slučaja.

5.2. Testiranje davatelja usluge

Drugi korak naše provjere ugovora je stvaranje testa za davatelja pomoću lažnog klijenta na temelju ugovora.

Implementacija našeg dobavljača potaknut će se ovim ugovorom na TDD način.

Za naš primjer koristit ćemo Spring Boot REST API.

Prvo, da bismo stvorili naš JUnit test, trebamo dodati ovisnost pact-jvm-provider-junit_2.11:

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

To nam omogućuje stvaranje JUnit testa pomoću PactRunner i navodeći naziv davatelja usluge i mjesto artefakta Pact:

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

Da bi ova konfiguracija funkcionirala, moramo postaviti test_consumer-test_provider.json datoteku u paktima mapa našeg REST servisnog projekta.

Zatim ćemo definirati cilj koji će se koristiti za provjeru interakcija u ugovoru i pokrenuti aplikaciju Spring Boot prije pokretanja testova:

@TestTarget javni konačni Target target = novi HttpTarget ("http", "localhost", 8082, "/ spring-rest"); privatna statička aplikacija ConfigurableWebApplicationContext; @BeforeClass public static void start () {application = (ConfigurableWebApplicationContext) SpringApplication.run (MainApplication.class); }

Na kraju ćemo navesti države u ugovoru koje želimo testirati:

@State ("test GET") javna praznina toGetState () {} @State ("test POST") javna praznina toPostState () {}

Pokretanje ove klase JUnit izvršit će dva testa za dva GET i POST zahtjeva. Pogledajmo zapisnik:

Provjera pakta između test_consumer i test_provider Dani test GET GET REQUEST vraća odgovor koji ima statusni kod 200 (OK) uključuje zaglavlja "Content-Type" s vrijednošću "application / json" (OK) ima odgovarajuće tijelo (OK) Provjera pakta između test_consumer i test_provider Dani test POST POST REQUEST vraća odgovor koji ima statusni kod 201 (OK) ima odgovarajuće tijelo (OK)

Imajte na umu da ovdje nismo uključili kod za stvaranje usluge REST. Potpuna usluga i test mogu se naći u projektu GitHub.

6. Zaključak

U ovom smo brzom vodiču pogledali potrošačke ugovore.

Stvorili smo ugovor koristeći Pakt knjižnica. Nakon što smo definirali ugovor, uspjeli smo testirati klijenta i uslugu u odnosu na ugovor i ustvrditi da su u skladu sa specifikacijama.

Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.