Integrationstest om foråret

1. Oversigt

Integrationstest spiller en vigtig rolle i applikationsudviklingscyklussen ved at verificere et systems ende-til-slut-opførsel.

I denne artikel vil vi se, hvordan vi kan udnytte Spring MVC-testrammen til at skrive og køre integrationstest, der tester controllere uden eksplicit at starte en Servlet-container.

2. Forberedelse

Følgende Maven-afhængigheder er nødvendige for at køre integrationstest som beskrevet i denne artikel. Først og fremmest de seneste JUnit- og Spring-testafhængigheder:

 junit junit 4.12 test org.springframework spring-test 4.3.2.RELEASE test 

For effektiv påstand om resultater vil vi også bruge Hamcrest og JSON-stien:

 org.hamcrest hamcrest-library 1.3 test com.jayway.jsonpath json-path 2.2.0 test 

3. Spring MVC Test Configuration

Lad os nu introducere, hvordan vi konfigurerer og kører de fjederaktiverede tests.

3.1. Aktivér forår i test

For det første vil enhver fjeder aktiveret test køre ved hjælp af @RunWith (SpringJUnit4ClassRunner.class); løberen er i det væsentlige indgangspunktet for at begynde at bruge Spring Test-rammen.

Vi har også brug for @ContextConfiguration kommentarer til at indlæse kontekstkonfigurationen og bootstrap den kontekst, som testen bruger.

Lad os kigge på det:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (klasser = {ApplicationConfig.class}) @WebAppConfiguration offentlig klasse GreetControllerIntegrationTest {....}

Bemærk hvordan, i @ContextConfiguration, vi leverede ApplicationConfig.class config klasse, der indlæser den konfiguration, vi har brug for til denne særlige test.

Vi brugte en Java-konfigurationsklasse her til at specificere kontekstkonfigurationen; på samme måde kan vi bruge den XML-baserede konfiguration:

@ContextConfiguration (locations = {""})

Endelig - testen er også kommenteret med @WebAppConfiguration - som vil indlæse webapplikationens kontekst.

Som standard ser det efter rodwebapplikationen på standardstien src / main / webapp; placeringen kan tilsidesættes ved at passere værdi attribut som:

@WebAppConfiguration (værdi = "")

3.2. Det WebApplicationContext Objekt

WebApplicationContext (wac) giver en webapplikationskonfiguration. Det indlæser alle applikationsbønner og controllere i konteksten.

Vi kan nu koble webapplikationskonteksten lige ind i testen:

@Autowired privat WebApplicationContext wac;

3.3. Mocking Web Context Beans

MockMvc yder support til Spring MVC-test. Det indkapsler alle webapplikationsbønner og gør dem tilgængelige til test.

Lad os se, hvordan du bruger det:

private MockMvc mockMvc; @Før offentlig ugyldig opsætning () kaster undtagelse {this.mockMvc = MockMvcBuilders.webAppContextSetup (this.wac) .build (); }

Vi er nødt til at initialisere mockMvc objekt i @Før kommenteret metode, så vi ikke behøver at initialisere den i hver test.

3.4. Bekræft testkonfiguration

For vores tutorial her, lad os faktisk kontrollere, at vi indlæser WebApplicationContext objekt (wac) korrekt. Vi kontrollerer også, at det rigtige servletContext bliver vedhæftet:

@Test offentlig ugyldighed givenWac_whenServletContext_thenItProvidesGreetController () {ServletContext servletContext = wac.getServletContext (); Assert.assertNotNull (servletContext); Assert.assertTrue (servletContext-forekomst af MockServletContext); Assert.assertNotNull (wac.getBean ("greetController")); }

Bemærk, at vi også kontrollerer, at vi a GreetController.java bønne findes i web-sammenhæng - hvilket sikrer, at fjederbønner indlæses korrekt.

På dette tidspunkt er opsætningen af ​​integrationstesten udført. Lad os se, hvordan vi kan teste ressourcemetoder ved hjælp af MockMvc objekt.

4. Skrivning af integrationstests

I dette afsnit gennemgår vi de grundlæggende operationer, der er tilgængelige gennem testrammen.

Vi viser, hvordan du sender anmodninger med stivariabler og parametre. Vi følger også med de få eksempler, der viser, hvordan man hævder, at det rigtige visningsnavn er løst, eller at svaret er som forventet.

Følgende uddrag bruger statisk import fra MockMvcRequestBuilders eller MockMvcResultMatchers klasser.

4.1. Bekræft visningsnavn

Lad os påberåbe sig / homePage slutpunkt fra vores test som:

// localhost: 8080 / spring-mvc-test /

eller

// localhost: 8080 / spring-mvc-test / homePage

Kodestykke:

@Test offentligt ugyldigt givenHomePageURI_whenMockMVC_thenReturnsIndexJSPViewName () {this.mockMvc.perform (get ("/ homePage")). AndDo (print ()). Og Expect (view (). Name ("index")); }

Lad os nedbryde det:

  • udføre() metoden kalder en get anmodningsmetode, som returnerer ResultatAktioner. Ved hjælp af dette resultat kan vi have påståede forventninger om svar som indhold, HTTP-status, header osv
  • andDo (udskriv ()) udskriver anmodningen og svaret. Dette er nyttigt for at få en detaljeret visning i tilfælde af fejl
  • andExpect ()vil forvente det medfølgende argument. I vores tilfælde forventer vi, at "indeks" returneres via MockMvcResultMatchers.view ()

4.2. Bekræft svarorganet

Vi påberåber os /hilse slutpunkt fra vores test som:

// localhost: 8080 / spring-mvc-test / greet

Forventet output:

{"id": 1, "message": "Hej verden !!!" }

Kodestykke:

@Test offentlig ugyldighed givenGreetURI_whenMockMVC_thenVerifyResponse () {MvcResult mvcResult = this.mockMvc.perform (get ("/ greet")). AndDo (print ()). AndExpect (status (). IsOk ()) .andExpect (jsonPath ("$) . besked "). værdi (" Hej verden !!! ")). og Retur (); Assert.assertEquals ("application / json; charset = UTF-8", mvcResult.getResponse (). GetContentType ()); }

Lad os se nøjagtigt, hvad der foregår:

  • andExpect (MockMvcResultMatchers.status (). isOk ())vil kontrollere, at svaret HTTP-status er Okay dvs. 200. Dette sikrer, at anmodningen blev udført
  • andExpect (MockMvcResultMatchers.jsonPath (“$. message”). værdi (“Hello World !!!”)) vil kontrollere, at svarindholdet matcher argumentet “Hej Verden!!!“. Her brugte vi jsonPath der udtrækker svarindhold og giver den ønskede værdi
  • og Retur ()vil returnere MvcResult objekt, der bruges, når vi skal verificere noget, som biblioteket ikke kan opnå. Du kan se, at vi har tilføjet hævderLige for at matche den indholdstype svar, der udvindes fra MvcResult objekt

4.3. Send Anmodning med stivariabel

Vi påberåber os / greetWithPathVariable / {name} slutpunkt fra vores test som:

// localhost: 8080 / spring-mvc-test / greetWithPathVariable / John

Forventet output:

{"id": 1, "message": "Hej verden John !!!" }

Kodestykke:

@Test offentligt ugyldigt givenGreetURIWithPathVariable_whenMockMVC_thenResponseOK () {this.mockMvc .perform (get ("/ greetWithPathVariable / {name}", "John")) .andDo (print ()). AndExpect (status (). IsOk ()) og. (content (). contentType ("application / json; charset = UTF-8")). og Expect (jsonPath ("$. meddelelse"). værdi ("Hello World John !!!")); }

MockMvcRequestBuilders.get (“/ greetWithPathVariable / {name}”, “John”) vil sende anmodning som “/ greetWithPathVariable / John“.

Dette bliver lettere med hensyn til læsbarhed og at vide, hvilke parametre der er angivet dynamisk i URL'en. Bemærk, at vi kan videregive så mange styparametre, som det er nødvendigt.

4.4. Sende Anmodning med forespørgselsparametre

Vi påberåber os / greetWithQueryVariable? name = {name} slutpunkt fra vores test som:

// localhost: 8080 / spring-mvc-test / greetWithQueryVariable? name = John% 20Doe

Forventet output:

{"id": 1, "message": "Hej verden John Doe !!!" }

Kodestykke:

@Test offentlig ugyldighed givenGreetURIWithQueryParameter_whenMockMVC_thenResponseOK () {this.mockMvc.perform (get ("/ greetWithQueryVariable") .param ("name", "John Doe")). Og Do (print ()). Og Expect (status () er. andExpect (content (). contentType ("application / json; charset = UTF-8")). og Expect (jsonPath ("$. message"). værdi ("Hello World John Doe !!!")); }

param ("navn", "John Doe") tilføjer forespørgselsparameteren i anmodning. Det ligner “ / greetWithQueryVariable? name = John% 20Doe“.

Forespørgselsparameteren kan også implementeres ved hjælp af URI-skabelonstil:

this.mockMvc.perform (get ("/ greetWithQueryVariable? name = {name}", "John Doe"));

4.5. Sende STOLPE Anmodning

Vi påberåber os / greetWithPost slutpunkt fra vores test som:

// localhost: 8080 / spring-mvc-test / greetWithPost

Forventet output:

{"id": 1, "message": "Hej verden !!!" }

Kodestykke:

@Test offentligt ugyldigt givetGreetURIWithPost_whenMockMVC_thenVerifyResponse () {this.mockMvc.perform (post ("/ greetWithPost")). Og gør (udskriv ()). Og Expect (status (). IsOk ()). Og Expect (indhold () .contentType (" application / json; charset = UTF-8 ")). og Expect (jsonPath (" $. message "). værdi (" Hello World !!! ")); }

MockMvcRequestBuilders.post (“/ greetWithPost”) sender postanmodningen. Stivariabler og forespørgselsparametre kan indstilles på en lignende måde, som vi kiggede tidligere, mens formulardata kan indstilles via param () metode, der kun ligner forespørgselsparameter som:

// localhost: 8080 / spring-mvc-test / greetWithPostAndFormData

Formulardata:

id = 1; navn = John% 20Doe

Forventet output:

{"id": 1, "message": "Hej verden John Doe !!!" }

Kodestykke:

@Test offentlig ugyldighed givenGreetURIWithPostAndFormData_whenMockMVC_thenResponseOK () {this.mockMvc.perform (post ("/ greetWithPostAndFormData"). Param ("id", "1") .param ("navn", "John Doe")). Og Do (udskriv (print) ogExpect (status (). isOk ()). og Expect (content (). contentType ("application / json; charset = UTF-8")). og Expect (jsonPath ("$. meddelelse"). værdi (" Hej Verden John Doe !!! ")). Og Forvent (jsonPath (" $. Id "). Værdi (1)); }

I ovenstående kodestykke har vi tilføjet to parametre id som "1" og navn som "John Doe".

5. MockMvc Begrænsninger

MockMvc giver en elegant og brugervenlig API til at ringe til webendepunkter og inspicere og hævde deres svar på samme tid. På trods af alle dens fordele har den et par begrænsninger.

Først og fremmest bruger den en underklasse af DispatcherServlet til at håndtere testanmodninger. For at være mere specifik, TestDispatcherServlet er ansvarlig for at ringe til controllere og udføre al den velkendte Spring Magic.

Det MockMvc klasse indpakker dette TestDispatcherServlet internt. Så hver gang vi sender en anmodning ved hjælp af udføre() metode, MockMvc vil bruge det underliggende TestDispatcherServlet direkte. Derfor, der er ikke oprettet nogen reelle netværksforbindelser, og derfor tester vi ikke hele netværksstakken under brug MockMvc.

Også,fordi Spring forbereder en falsk webapplikationskontekst til at spotte HTTP-anmodninger og svar, understøtter den muligvis ikke alle funktioner i en fuldt sprunget Spring-applikation.

For eksempel understøtter denne mock-opsætning ikke HTTP-omdirigeringer. Dette virker måske ikke så vigtigt i starten. Spring Boot håndterer dog nogle fejl ved at omdirigere den aktuelle anmodning til /fejl slutpunkt. Så hvis vi bruger MockMvc, vi kan muligvis ikke teste nogle API-fejl.

Som et alternativ til MockMvc, vi kan oprette en mere reel applikationskontekstog brug derefter RestTemplate eller endda være sikker på at teste vores ansøgning.

For eksempel er dette let ved hjælp af Spring Boot:

@RunWith (SpringRunner.class) @SpringBootTest (webEnvironment = RANDOM_PORT) offentlig klasse GreetControllerRealIntegrationTest {@LocalServerPort privat int-port; @Før offentlig ugyldig setUp () {RestAssured.port = port; } @Test offentlig ugyldighed givenGreetURI_whenSendingReq_thenVerifyResponse () {given (). Get ("/ greet") .then () .statusCode (200); }}

På denne måde vil hver test foretage en reel HTTP-anmodning til applikationen, der lytter til en tilfældig TCP-port.

6. Konklusion

I denne vejledning implementerede vi et par enkle Spring-aktiverede integrationstest.

Vi kiggede også på WebApplicationContext og MockMVC oprettelse af objekter, som spillede en vigtig rolle i at kalde applikationens slutpunkter.

Ser vi videre, dækkede vi, hvordan vi kan sende og STOLPE anmodninger med variationer af parameteroverføring og hvordan man verificerer HTTP-svarstatus, header og indhold.

Som en afsluttende bemærkning vurderede vi også nogle begrænsninger af MockMvc. At kende disse begrænsninger kan guide os til at træffe en informeret beslutning om, hvordan vi skal gennemføre vores tests.

Endelig er implementeringen af ​​alle disse eksempler og kodestykker tilgængelig i GitHub.


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