Introduktion til WireMock

1. Oversigt

WireMock er et bibliotek til stubbing og mocking af webtjenester. Det konstruerer en HTTP-server, som vi kunne oprette forbindelse til, som vi ville gøre med en faktisk webtjeneste.

Når en WireMock-server er i aktion, kan vi oprette forventninger, ringe til tjenesten og derefter kontrollere dens adfærd.

2. Maven-afhængigheder

For at kunne drage fordel af WireMock-biblioteket er vi nødt til at inkludere følgende afhængighed i POM:

 com.github.tomakehurst wiremock 1.58 test 

3. Programmatisk administreret server

Dette afsnit dækker måden manuelt konfigurerer en WireMock-server på. dvs. uden understøttelse af JUnit auto-konfiguration. Brugen demonstreres af en meget enkel stub.

3.1. Serveropsætning

En WireMock-server kan instantieres således:

WireMockServer wireMockServer = ny WireMockServer (streng vært, int port);

Hvis der ikke gives argumenter, er serverværten som standard lokal vært og serverporten til 8080.

Serveren kan derefter startes og stoppes ved hjælp af to enkle metoder:

wireMockServer.start ();

Og:

wireMockServer.stop ();

3.2. Grundlæggende brug

WireMock-biblioteket vil først blive demonstreret ved en grundlæggende anvendelse, hvor der gives en stub til en nøjagtig URL uden yderligere konfiguration. Lad os oprette en serverforekomst:

WireMockServer wireMockServer = ny WireMockServer ();

WireMock-serveren skal køre, før klienten opretter forbindelse til den:

wireMockServer.start ();

Webservicen stubbes derefter:

configureFor ("localhost", 8080); stubFor (get (urlEqualTo ("/ baeldung")). willReturn (aResponse (). withBody ("Welcome to Baeldung!")));

Denne tutorial bruger Apache HttpClient API til at repræsentere en klient, der opretter forbindelse til serveren:

CloseableHttpClient httpClient = HttpClients.createDefault ();

En anmodning udføres, og et svar returneres henholdsvis bagefter:

HttpGet anmodning = ny HttpGet ("// localhost: 8080 / baeldung"); HttpResponse httpResponse = httpClient.execute (anmodning);

Vi konverterer httpResponse variabel til en Snor ved hjælp af en hjælper metode:

String responseString = convertResponseToString (httpResponse);

Her er implementeringen af ​​denne konverteringshjælpermetode:

private String convertResponseToString (HttpResponse respons) kaster IOException {InputStream responseStream = respons.getEntity (). getContent (); Scannerscanner = ny scanner (responseStream, "UTF-8"); String responseString = scanner.useDelimiter ("\ Z"). Næste (); scanner.close (); returnere responsString; }

Følgende kode bekræfter, at serveren har modtaget en anmodning om den forventede URL, og svaret, der kommer til klienten, er nøjagtigt det, der blev sendt:

verificere (getRequestedFor (urlEqualTo ("/ baeldung")); assertEquals ("Velkommen til Baeldung!", stringResponse);

Endelig skal WireMock-serveren stoppes for at frigive systemressourcer:

wireMockServer.stop ();

4. JUnit Managed Server

I modsætning til afsnit 3 illustrerer dette afsnit brugen af ​​en WireMock-server ved hjælp af JUnit Herske.

4.1. Serveropsætning

En WireMock-server kan integreres i JUnit-testsager ved hjælp af @Herske kommentar. Dette gør det muligt for JUnit at styre livscyklussen, starte serveren før hver testmetode og stoppe den, når metoden vender tilbage.

På samme måde som den programmatisk styrede server kan en JUnit-styret WireMock-server oprettes som et Java-objekt med det givne portnummer:

@Rule public WireMockRule wireMockRule = ny WireMockRule (int-port);

Hvis der ikke leveres argumenter, tager serverporten standardværdien, 8080. Serverhost, som standard lokal vært, og andre konfigurationer kan specificeres ved hjælp af Muligheder interface.

4.2. URL Matching

Efter opsætning af en WireMockRule For eksempel er det næste trin at konfigurere en stub. I dette underafsnit leverer vi en REST-stub til et serviceendepunkt ved hjælp af regulært udtryk:

stubFor (get (urlPathMatching ("/ baeldung /.*")) .willReturn (aResponse () .withStatus (200) .withHeader ("Content-Type", "application / json") .withBody ("\" test-bibliotek \ ": \" WireMock \ "")));

Lad os gå videre til at oprette en HTTP-klient, udføre en anmodning og modtage et svar:

CloseableHttpClient httpClient = HttpClients.createDefault (); HttpGet anmodning = ny HttpGet ("// localhost: 8080 / baeldung / wiremock"); HttpResponse httpResponse = httpClient.execute (anmodning); String stringResponse = convertHttpResponseToString (httpResponse);

Ovenstående kodestykke udnytter en metode til konverteringshjælper:

private String convertHttpResponseToString (HttpResponse httpResponse) kaster IOException {InputStream inputStream = httpResponse.getEntity (). getContent (); return convertInputStreamToString (inputStream); }

Dette gør igen brug af en anden privat metode:

private String convertInputStreamToString (InputStream inputStream) {Scannerscanner = ny Scanner (inputStream, "UTF-8"); Strengstreng = scanner.useDelimiter ("\ Z"). Næste (); scanner.close (); returstreng; }

Stubens operationer verificeres af nedenstående testkode:

verificere (getRequestedFor (urlEqualTo ("/ baeldung / wiremock")); assertEquals (200, httpResponse.getStatusLine (). getStatusCode ()); assertEquals ("application / json", httpResponse.getFirstHeader ("Content-Type"). getValue ()); assertEquals ("\" test-bibliotek \ ": \" WireMock \ "", stringResponse);

4.3. Anmod om header-matching

Nu vil vi demonstrere, hvordan man stubber en REST API med matchning af overskrifter. Lad os starte med stubkonfigurationen:

stubFor (get (urlPathEqualTo ("/ baeldung / wiremock")) .withHeader ("Accept", matching ("text /.*")) .willReturn (aResponse () .withStatus (503) .withHeader ("Content-Type" , "text / html") .withBody ("!!! Service ikke tilgængelig !!!")));

I lighed med det foregående underafsnit illustrerer vi HTTP-interaktion ved hjælp af HttpClient API ved hjælp af de samme hjælpemetoder:

CloseableHttpClient httpClient = HttpClients.createDefault (); HttpGet anmodning = ny HttpGet ("// localhost: 8080 / baeldung / wiremock"); request.addHeader ("Accepter", "tekst / html"); HttpResponse httpResponse = httpClient.execute (anmodning); String stringResponse = convertHttpResponseToString (httpResponse);

Følgende verifikation og påstande bekræfter funktionerne i den stub, vi oprettede før:

verificere (getRequestedFor (urlEqualTo ("/ baeldung / wiremock")); assertEquals (503, httpResponse.getStatusLine (). getStatusCode ()); assertEquals ("text / html", httpResponse.getFirstHeader ("Content-Type"). getValue ()); assertEquals ("!!! Service ikke tilgængelig !!!", stringResponse);

4.4. Anmod om kropsmatch

WireMock-biblioteket kan også bruges til at stubbe en REST API med body matching. Her er konfigurationen til en stub af denne art:

stubFor (post (urlEqualTo ("/ baeldung / wiremock")) .withHeader ("Content-Type", equalTo ("application / json")) .withRequestBody (indeholder ("\" test-bibliotek \ ": \" WireMock \ "")) .withRequestBody (indeholdende ("\" skaber \ ": \" Tom Akehurst \ "")) .withRequestBody (indeholdende ("\" website \ ": \" wiremock.org \ "")) .willReturn ( aResponse () .medStatus (200)));

Nu er det tid til at oprette en StringEntity objekt, der vil blive brugt som brødtekst i en anmodning:

InputStream jsonInputStream = this.getClass (). GetClassLoader (). GetResourceAsStream ("wiremock_intro.json"); String jsonString = convertInputStreamToString (jsonInputStream); StringEntity-enhed = ny StringEntity (jsonString);

Koden ovenfor bruger en af ​​de konverteringshjælpemetoder, der er defineret før, convertInputStreamToString.

Her er indholdet af wiremock_intro.json fil på klassestien:

{"testing-library": "WireMock", "creator": "Tom Akehurst", "website": "wiremock.org"}

HTTP-anmodninger og svar kan konfigureres og udføres som følger:

CloseableHttpClient httpClient = HttpClients.createDefault (); HttpPost-anmodning = ny HttpPost ("// localhost: 8080 / baeldung / wiremock"); request.addHeader ("Content-Type", "application / json"); request.setEntity (enhed); HttpResponse svar = httpClient.execute (anmodning);

Dette er testkoden, der bruges til at validere stubben:

verificere (postRequestedFor (urlEqualTo ("/ baeldung / wiremock")). medHeader ("Content-Type", equalTo ("application / json"))); assertEquals (200, respons.getStatusLine (). getStatusCode ());

4.5. Stubprioritet

De tidligere underafsnit beskæftiger sig med situationer, hvor en HTTP-anmodning kun matcher en enkelt stub. Det ville være mere kompliceret, hvis der er mere end et match til en anmodning. Som standard har den senest tilføjede stub forrang i et sådant tilfælde. Imidlertid har brugerne lov til at tilpasse denne adfærd for at tage mere kontrol over WireMock-stubs.

Vi demonstrerer, hvordan en WireMock-server fungerer, når en kommende anmodning matcher to forskellige stubber med og uden at indstille prioritetsniveauet på samme tid. Begge scenarier bruger følgende private hjælpemetode:

private HttpResponse generererClientAndReceiveResponseForPriorityTests () kaster IOException {CloseableHttpClient httpClient = HttpClients.createDefault (); HttpGet anmodning = ny HttpGet ("// localhost: 8080 / baeldung / wiremock"); request.addHeader ("Accepter", "tekst / xml"); returner httpClient.execute (anmodning); }

For det første skal du konfigurere to stubber uden hensyntagen til prioritetsniveauet:

stubFor (get (urlPathMatching ("/ baeldung /.*")) .willReturn (aResponse () .withStatus (200))); stubFor (get (urlPathEqualTo ("/ baeldung / wiremock")) .withHeader ("Accept", matching ("text /.*")) .willReturn (aResponse () .withStatus (503)));

Opret derefter en HTTP-klient og udfør en anmodning ved hjælp af hjælpemetoden beskrevet ovenfor:

HttpResponse httpResponse = genererClientAndReceiveResponseForPriorityTests ();

Følgende kodestykke verificerer, at den sidst konfigurerede stub anvendes uanset den, der er defineret før, når en anmodning matcher dem begge:

verificere (getRequestedFor (urlEqualTo ("/ baeldung / wiremock")); assertEquals (503, httpResponse.getStatusLine (). getStatusCode ());

Lad os gå videre til stubber, hvor prioritetsniveauer er indstillet, hvor et lavere tal repræsenterer en højere prioritet:

stubFor (get (urlPathMatching ("/ baeldung /.*")) .atPriority (1) .willReturn (aResponse () .withStatus (200))); stubFor (get (urlPathEqualTo ("/ baeldung / wiremock")) .atPriority (2) .withHeader ("Accept", matching ("text /.*")) .willReturn (aResponse () .withStatus (503)));

Oprettelse og udførelse af en HTTP-anmodning:

HttpResponse httpResponse = genererClientAndReceiveResponseForPriorityTests ();

Følgende kode validerer effekten af ​​prioritetsniveauer, hvor den første konfigurerede stub anvendes i stedet for den sidste:

verificere (getRequestedFor (urlEqualTo ("/ baeldung / wiremock")); assertEquals (200, httpResponse.getStatusLine (). getStatusCode ());

5. Konklusion

Denne tutorial introducerede WireMock, og hvordan man konfigurerer samt konfigurerer dette bibliotek til test af REST API'er ved hjælp af forskellige teknikker, herunder matching af URL, anmodningsoverskrifter og body.

Implementeringen af ​​alle eksemplerne og kodestykkerne kan findes i et GitHub-projekt.