Programavimas

„JUnit 5“ mokymo programa, 2 dalis: įrenginio testavimo spyruoklės MVC su „JUnit 5“

Pavasario MVC yra viena iš populiariausių „Java“ struktūrų kuriant įmonės „Java“ programas, ir ji labai tinka testavimui. Pagal savo planą „Spring MVC“ skatina atskirti rūpesčius ir skatina koduoti sąsajas. Dėl šių savybių kartu su pavasariu įdiegta priklausomybės injekcija pavasario programas galima labai išbandyti.

Ši pamoka yra antra mano įvado į įrenginių testavimą naudojant „JUnit 5“ pusę. Aš jums parodysiu, kaip integruoti „JUnit 5“ su „Spring“, tada supažindinsiu jus su trim įrankiais, kuriais galėsite išbandyti „Spring MVC“ valdiklius, paslaugas ir saugyklas.

atsisiųsti Gauti kodą Atsisiųskite šioje pamokoje naudojamų programų, pavyzdžiui, šaltinio kodą. Stevenas Hainesas sukūrė „JavaWorld“.

JUnit 5 integravimas su 5 spyruokle

Šioje pamokoje mes naudojame „Maven“ ir „Spring Boot“, todėl pirmas dalykas, kurį turime padaryti, yra pridėti „JUnit 5“ priklausomybę prie „Maven POM“ failo:

  org.junit.jupiter junit-jupiter 5.6.0 testas 

Kaip ir tai darėme 1 dalyje, šiame pavyzdyje naudosime „Mockito“. Taigi reikės pridėti „JUnit 5 Mockito“ biblioteką:

  org.mockito mockito-junit-jupiter 3.2.4 testas 

@ExtendWith ir „SpringExtension“ klasė

5 JUnitas apibrėžia plėtinio sąsaja, per kurią klasės gali integruotis į „JUnit“ testus įvairiuose vykdymo gyvavimo ciklo etapuose. Galime įgalinti plėtinius pridėdami @ExtendWith anotacija mūsų bandymų klasėms ir nurodoma įkeliamos pratęsimo klasė. Tada plėtinys gali įdiegti įvairias atgalinio ryšio sąsajas, kurios bus naudojamos per visą bandymo gyvavimo ciklą: prieš pradedant visus bandymus, prieš kiekvieną bandymą, po kiekvieno bandymo ir po to, kai visi bandymai buvo atlikti.

Pavasaris apibrėžia a Pavasario pratęsimas klasė, užsiprenumeravusi „JUnit 5“ gyvavimo ciklo pranešimus, norėdama sukurti ir palaikyti „bandomąjį kontekstą“. Primename, kad „Spring“ programos kontekste yra visos pavasario pupelės programoje ir kad ji atlieka priklausomybės injekciją, kad sujungtų programą ir jos priklausomybes. „Spring“ naudoja „JUnit 5“ plėtinio modelį, kad išlaikytų testo taikymo kontekstą, todėl rašymo vieneto testai su „Spring“ yra aiškūs.

Pridėję JUnit 5 biblioteką prie savo „Maven POM“ failo, galime naudoti SpringExtension.class pratęsti mūsų „JUnit 5“ testų klases:

 @ExtendWith (SpringExtension.class) klasės „MyTests“ {// ...}

Šiuo atveju pavyzdys yra „Spring Boot“ programa. Laimei @SpringBootTest anotacijoje jau yra @ExtendWith (SpringExtension.class) anotacija, todėl mums tereikia įtraukti @SpringBootTest.

Pridedant „Mockito“ priklausomybę

Norėdami tinkamai išbandyti kiekvieną komponentą atskirai ir imituoti skirtingus scenarijus, norėsime sukurti bandomąjį kiekvienos klasės priklausomybės įgyvendinimą. Čia yra „Mockito“. Įtraukite šią priklausomybę į savo POM failą, kad pridėtumėte „Mockito“ palaikymą:

  org.mockito mockito-junit-jupiter 3.2.4 testas 

Integravę „JUnit 5“ ir „Mockito“ į savo „Spring“ programą, galite pasinaudoti „Mockito“ naudodami savo testo klasėje paprasčiausiai apibrėždami pavasarinę pupelę (pvz., Paslaugą ar saugyklą) naudodami @MockBean anotacija. Štai mūsų pavyzdys:

 @SpringBootTest viešosios klasės „WidgetServiceTest“ {/ ** * „Autowire“ paslaugoje, kurią norime išbandyti * / @Autowired private WidgetService service; / ** * Sukurti WidgetRepository * / @MockBean private WidgetRepository talpyklą; ...} 

Šiame pavyzdyje mes kuriame maketą „WidgetRepository“ mūsų viduje „WidgetServiceTest“ klasė. Kai Pavasaris tai pamatys, jis automatiškai sujungs mus „WidgetService“ kad galėtume sukurti skirtingus scenarijus savo bandymų metoduose. Kiekvienas bandymo metodas sukonfigūruos „WidgetRepository“, pavyzdžiui, grąžindami prašomą Valdiklis arba grąžinant Pasirenkama. Tuščia () užklausai, kurios duomenys nerandami. Likusią šios mokymo dalies dalį praleisime ieškodami įvairių būdų, kaip sukonfigūruoti šias maketuotas pupeles.

Pavasario MVC pavyzdinė programa

Norėdami parašyti pavasarinius vieneto testus, mums reikia programos, kuriai prieš juos parašyti. Laimei, galime naudoti mano pavyzdinę programą Pavasario serija pamoka "Pavasario sistemos 5 įvaldymas, 1 dalis: pavasario MVC". Aš naudoju tos mokymo programos pavyzdinę programą kaip pagrindinę programą. Pakeičiau ją naudodamas stipresnę REST API, kad turėtume išbandyti dar keletą dalykų.

Programos pavyzdys yra „Spring MVC“ žiniatinklio programa su REST valdikliu, paslaugų lygiu ir saugykla, kuri naudoja „Spring Data JPA“, kad išlaikytų „valdiklius“ į H2 atminties duomenų bazę ir iš jos. 1 paveiksle pateikiama apžvalga.

Stevenas Hainesas

Kas yra valdiklis?

A Valdiklis yra tik „daiktas“ su ID, pavadinimu, aprašymu ir versijos numeriu. Šiuo atveju mūsų valdikliui pridedamos JPA anotacijos, kad jis būtų apibrėžtas kaip subjektas. „WidgetRestController“ yra pavasario MVC valdiklis, kuris RESTful API kvietimus paverčia veiksmais, kuriuos reikia atlikti Valdikliai. „WidgetService“ yra standartinė pavasario paslauga, apibrėžianti verslo funkcionalumą Valdikliai. Galiausiai „WidgetRepository“ yra „Spring Data“ JPA sąsaja, kuriai „Spring“ sukurs įgyvendinimą vykdymo metu. Rašydami testus, mes peržiūrėsime kiekvienos klasės kodą kitose dalyse.

Padalinys išbando pavasario paslaugą

Pradėkime nuo peržiūros, kaip išbandyti pavasarįpaslaugą, nes tai yra lengviausias mūsų MVC programos komponentas. Šio skyriaus pavyzdžiai leis mums ištirti „JUnit 5“ integraciją su „Spring“ neįvedant jokių naujų testavimo komponentų ar bibliotekų, nors tai padarysime vėliau pamokoje.

Pirmiausia peržiūrėsime „WidgetService“ sąsaja ir „WidgetServiceImpl“ klasės, kurios rodomos atitinkamai 1 ir 2 sąrašuose.

Sąrašas 1. „Spring“ paslaugų sąsaja (WidgetService.java)

 paketas com.geekcap.javaworld.spring5mvcexample.service; importuoti com.geekcap.javaworld.spring5mvcexample.model.Widget; importuoti java.util.List; importuoti java.util.Privaloma; viešoji sąsaja „WidgetService“ {Neprivaloma „findById“ (ilgas ID); Sąrašas findAll (); Valdiklio išsaugojimas (Valdiklio valdiklis); void deleteById (ilgas ID); }

2 sąrašas. Pavasario paslaugų diegimo klasė (WidgetServiceImpl.java)

 paketas com.geekcap.javaworld.spring5mvcexample.service; importuoti com.geekcap.javaworld.spring5mvcexample.model.Widget; importuoti com.geekcap.javaworld.spring5mvcexample.repository.WidgetRepository; importuoti com.google.common.collect.Lists; importuoti org.springframework.stereotype.Service; importuoti java.util.ArrayList; importuoti java.util.List; importuoti java.util.Privaloma; @Service viešoji klasė „WidgetServiceImpl“ įgyvendina „WidgetService“ {privačią „WidgetRepository“ saugyklą; public WidgetServiceImpl (WidgetRepository repository) {this.repository = saugykla; } @Paisyti viešą Pasirenkamas „findById“ (ilgas ID) {return repository.findById (id); } @Paisyti viešąjį sąrašą findAll () {return Lists.newArrayList (repository.findAll ()); } @Paisyti viešą valdiklių išsaugojimą (valdiklių valdiklis) {// Padidinkite versijos numerį widget.setVersion (widget.getVersion () + 1); // Įrašykite valdiklį į saugyklą grąžinkite saugyklą.save (valdiklis); } @Paisyti viešą nieką deleteById (ilgas ID) {repository.deleteById (id); }}

„WidgetServiceImpl“ yra pavasario paslauga, anotuota @Service anotacija, turinti a „WidgetRepository“ prijungtas prie jo per jo konstruktorių. „findById“ (), findAll ()ir deleteById () metodai yra visi pagrindiniai metodai „WidgetRepository“. Vienintelė verslo logika, kurią rasite, yra sutaupyti() metodas, kuris padidina. versijos numerį Valdiklis kai jis išsaugomas.

Testo klasė

Norėdami išbandyti šią klasę, turime sukurti ir sukonfigūruoti maketą „WidgetRepository“, prijunkite jį prie „WidgetServiceImpl“ pavyzdžiui, ir tada prijunkite „WidgetServiceImpl“ į mūsų testų klasę. Laimei, tai kur kas lengviau, nei atrodo. 3 sąraše rodomas šaltinio kodas „WidgetServiceTest“ klasė.

3 sąrašas. Pavasario paslaugų testo klasė (WidgetServiceTest.java)

 paketas com.geekcap.javaworld.spring5mvcexample.service; importuoti com.geekcap.javaworld.spring5mvcexample.model.Widget; importuoti com.geekcap.javaworld.spring5mvcexample.repository.WidgetRepository; importuoti org.junit.jupiter.api.Aertertions; importuoti org.junit.jupiter.api.DisplayName; importuoti org.junit.jupiter.api.Test; importuoti org.junit.jupiter.api.extension.ExtendWith; importuoti org.springframework.beans.factory.annotation.Autowired; importuoti org.springframework.boot.test.context.SpringBootTest; importuoti org.springframework.boot.test.mock.mockito.MockBean; importuoti org.springframework.test.context.junit.jupiter.SpringExtension; importuoti java.util.Arrays; importuoti java.util.List; importuoti java.util.Privaloma; importuoti statinį org.mockito.Mockito.doReturn; importuoti statinį org.mockito.ArgumentMatchers.any; @SpringBootTest viešosios klasės „WidgetServiceTest“ {/ ** * „Autowire“ paslaugoje, kurią norime išbandyti * / @Autowired private WidgetService service; / ** * Sukurti WidgetRepository * / @MockBean private WidgetRepository talpyklą; @Test @DisplayName ("Test findById Success") void testFindById () {// Nustatykite savo maketo saugyklą Valdiklio valdiklis = naujas valdiklis (1l, "Valdiklio pavadinimas", "Aprašymas", 1); doReturn (Pasirenkama. (valdikliui)). kai (saugykla) .findById (1l); // Vykdyti tarnybinį iškvietimą Pasirenkama returnWidget = service.findById (1l); // Tvirtinkite atsakymą Assertions.assertTrue (returnWidget.isPresent (), "Valdiklis nerastas"); „Assertions.assertSame“ (returnWidget.get (), valdiklis, „Grąžintas valdiklis nebuvo tas pats, kaip maketas“); } @Test @DisplayName („Test findById Not Found“) void testFindByIdNotFound () {// Nustatykite savo maketo repliką „doReturn“ („Optional.empty“ ()). Kai (saugykla). // Vykdyti tarnybinį iškvietimą Pasirenkama returnWidget = service.findById (1l); // Tvirtinkite atsakymą Assertions.assertFalse (returnWidget.isPresent (), "Valdiklio negalima rasti"); } @Test @DisplayName ("Test findAll") void testFindAll () {// Nustatykite savo maketo saugyklą Valdiklio valdiklis1 = naujas valdiklis (1l, "Valdiklio pavadinimas", "Aprašymas", 1); Valdiklio valdiklis2 = naujas valdiklis (2l, „2 valdiklio pavadinimas“, „2 aprašas“, 4); doReturn (Arrays.asList (widget1, widget2)). kai (saugykla) .findAll (); // Vykdykite paslaugų skambučių sąrašo valdiklius = service.findAll (); // Tvirtinkite atsakymą Assertions.assertEquals (2, widgets.size (), "findAll turėtų grąžinti 2 valdiklius"); } @Test @DisplayName ("Test save widget") void testSave () {// Nustatykite savo maketo saugyklą Valdiklių valdiklis = naujas valdiklis (1l, "Valdiklio pavadinimas", "Aprašas", 1); doReturn (valdiklis) .kada (saugykla) .saugoti (bet koks ()); // Vykdykite tarnybos skambutį Widget ReturnWidget = service.save (valdiklis); // Tvirtinkite atsakymą Assertions.assertNotNull (returnWidget, "Išsaugotas valdiklis neturėtų būti nulinis"); Assertions.assertEquals (2, returnWidget.getVersion (), "Versija turėtų būti didinama"); }} 

„WidgetServiceTest“ klasė yra pažymėta @SpringBootTest anotacija, kuria nuskaitoma CLASSPATH visoms „Spring“ konfigūracijos klasėms ir pupelėms bei sukuria „Spring“ taikymo kontekstą bandymų klasei. Prisimink tai „WidgetServiceTest“ taip pat netiesiogiai apima @ExtendWith (SpringExtension.class) anotacija per @SpringBootTest anotacija, integruojanti testo klasę su „JUnit 5“.

Testo klasėje taip pat naudojami „Spring“ @Autowired anotacija automatiniam prisijungimui a „WidgetService“ norint išbandyti, ir jis naudoja „Mockito“ @MockBean anotacija sukurti pašaipą „WidgetRepository“. Šiuo metu turime pašaipą „WidgetRepository“ kad mes galime sukonfigūruoti, ir tikras „WidgetService“ su pašaipa „WidgetRepository“ laidas į jį.

„Pavasario“ paslaugos išbandymas

Pirmasis bandymo metodas, testFindById (), vykdo „WidgetService“'s „findById“ () metodas, kuris turėtų grąžinti Neprivaloma kuriame yra a Valdiklis. Mes pradedame kurti Valdiklis kad mes norime „WidgetRepository“ Grįžti. Tada mes naudojame „Mockito“ API konfigūruoti „WidgetRepository“ :: findById metodas. Mūsų bandomosios logikos struktūra yra tokia:

 „doReturn“ (VALUE_TO_RETURN). kai (MOCK_CLASS_INSTANCE). MOCK_METHOD 

Šiuo atveju sakome: grąžinti an Neprivaloma mūsų Valdiklis kai kapinyno „findById“ () metodas iškviečiamas argumentu 1 (kaip a ilgas).

Toliau mes pasitelkiame „WidgetService“'s findById metodas su argumentu 1. Tada mes patvirtiname, kad jis yra ir kad grąžinamas Valdiklis yra tas, kurį mes sukonfigūravome „WidgetRepository“ Grįžti.