Programiranje

Vadnica za JUnit 5, 2. del: Enotno preskušanje Spring MVC z JUnit 5

Spring MVC je eden izmed najbolj priljubljenih okvirov Java za gradnjo aplikacij Java za podjetja in se zelo dobro preizkuša. Spring MVC po svoji zasnovi spodbuja ločevanje skrbi in spodbuja kodiranje vmesnikov. Te lastnosti, skupaj s Springovim izvajanjem vbrizgavanja odvisnosti, naredijo Spring aplikacije zelo preverljive.

Ta vadnica je druga polovica mojega uvoda v enotno testiranje z JUnit 5. Pokazal vam bom, kako integrirati JUnit 5 s Springom, nato pa vam predstavil tri orodja, s katerimi lahko preizkusite krmilnike, storitve in skladišča Spring MVC.

prenos Prenesite kodo Prenesite izvorno kodo, na primer za programe, uporabljene v tej vadnici. Ustvaril Steven Haines za JavaWorld.

Integriranje JUnit 5 z vzmetjo 5

Za to vadnico uporabljamo Maven in Spring Boot, zato moramo najprej dodati odvisnost JUnit 5 v našo datoteko Maven POM:

  org.junit.jupiter test junit-jupiter 5.6.0 

Tako kot v prvem delu bomo za ta primer uporabili Mockito. Torej, dodati bomo morali knjižnico JUnit 5 Mockito:

  org.mockito mockito-junit-jupiter 3.2.4 test 

@ExtendWith in razred SpringExtension

JUnit 5 definira razširitveni vmesnik, prek katerega se lahko razredi integrirajo s preskusi JUnit na različnih stopnjah življenjskega cikla izvedbe. Razširitve lahko omogočimo z dodajanjem @ExtendWith pripis k našim testnim razredom in določitev razreda razširitve za nalaganje. Nato lahko razširitev implementira različne vmesnike za povratni klic, ki se bodo sprožili v celotnem življenjskem ciklu preskusa: pred zagonom vseh preskusov, pred vsakim preizkusom, po vsakem preizkusu in po tem, ko se bodo vsi preskusi zagnali.

Pomlad določa a SpringExtention razred, ki se naroči na obvestila o življenjskem ciklusu JUnit 5, da ustvari in vzdržuje "testni kontekst". Spomnimo se, da kontekst aplikacije Spring vsebuje vse spomladanske zrnje v aplikaciji in da izvaja vbrizganje odvisnosti, da poveže aplikacijo in njene odvisnosti. Spring uporablja model razširitve JUnit 5 za vzdrževanje konteksta aplikacije testa, zaradi česar je pisanje enotnih testov s Springom enostavno.

Ko smo datoteki POM Maven dodali knjižnico JUnit 5, lahko uporabimo datoteko SpringExtension.class za podaljšanje naših testnih razredov JUnit 5:

 @ExtendWith (SpringExtension.class) razred MyTests {// ...}

Primer v tem primeru je aplikacija Spring Boot. Na srečo @SpringBootTest pripis že vključuje @ExtendWith (SpringExtension.class) pripis, zato moramo samo vključiti @SpringBootTest.

Dodajanje odvisnosti Mockito

Če želite pravilno preizkusiti posamezno komponento in simulirati različne scenarije, bomo želeli ustvariti lažne izvedbe odvisnosti vsakega razreda. Tukaj prihaja Mockito. V datoteko POM vključite naslednjo odvisnost, da dodate podporo za Mockito:

  org.mockito mockito-junit-jupiter 3.2.4 test 

Ko v aplikacijo Spring vključite JUnit 5 in Mockito, lahko Mockito izkoristite tako, da v svojem testnem razredu preprosto določite Spring fižol (kot je storitev ali repozitorij) @MockBean pripis. Tu je naš primer:

 @SpringBootTest javni razred WidgetServiceTest {/ ** * Autowire v storitvi, ki jo želimo preizkusiti * / @Autowired zasebna storitev WidgetService; / ** * Ustvari lažno izvedbo WidgetRepository * / @MockBean zasebnega repozitorija WidgetRepository; ...} 

V tem primeru ustvarjamo posnetek WidgetRepository znotraj našega WidgetServiceTest razred. Ko bo pomlad to videla, jo bo samodejno povezala v našo WidgetService tako da lahko v naših testnih metodah ustvarimo različne scenarije. Vsaka preskusna metoda bo konfigurirala vedenje WidgetRepository, na primer z vrnitvijo zahtevanega Pripomoček ali vrnitev Neobvezno.prazno () za poizvedbo, za katero podatkov ni mogoče najti. Preostanek te vadnice bomo porabili za ogled primerov različnih načinov konfiguriranja teh lažnih fižolov.

Primer aplikacije Spring MVC

Za pisanje preskusov enot, ki temeljijo na pomladi, potrebujemo aplikacijo, s katero jih bomo napisali. Na srečo lahko uporabimo primer aplikacije iz mojega Pomladna serija vadnica "Obvladovanje Spring Spring 5, 1. del: Spring MVC." Primer aplikacije iz te vadnice sem uporabil kot osnovno aplikacijo. Prilagodil sem ga z močnejšim REST API-jem, tako da smo imeli še nekaj stvari za preizkus.

Primer aplikacije je spletna aplikacija Spring MVC s krmilnikom REST, servisno plastjo in skladiščem, ki uporablja Spring Data JPA za vztrajanje "gradnikov" v in iz baze podatkov H2 v pomnilniku. Slika 1 je pregled.

Steven Haines

Kaj je pripomoček?

A Pripomoček je samo "stvar" z ID-jem, imenom, opisom in številko različice. V tem primeru je naš pripomoček označen s pripisi JPA, da ga definiramo kot entiteto. The WidgetRestController je Spring MVC krmilnik, ki pretvori klice API RESTful v dejanja, ki jih je treba izvesti Pripomočki. The WidgetService je standardna storitev Spring, ki opredeljuje poslovno funkcionalnost za Pripomočki. Končno, WidgetRepository je Spring Data JPA vmesnik, za katerega bo Spring ustvaril izvedbo med izvajanjem. Kodo za vsak razred bomo pregledali, saj bomo v naslednjih poglavjih pisali teste.

Enotno testiranje storitve Spring

Začnimo s pregledom preizkusa vzmetistoritev, ker je to najlažje preizkusiti komponento v naši aplikaciji MVC. Primeri v tem razdelku nam bodo omogočili, da raziščemo integracijo JUnit 5 s Springom, ne da bi uvedli nove preizkusne komponente ali knjižnice, čeprav bomo to storili kasneje v vadnici.

Začeli bomo s pregledom WidgetService vmesnik in WidgetServiceImpl razreda, ki sta prikazani na seznamu 1 in seznamu 2.

Seznam 1. Vmesnik storitve Spring (WidgetService.java)

 paket com.geekcap.javaworld.spring5mvcexample.service; uvoz com.geekcap.javaworld.spring5mvcexample.model.Widget; uvoz java.util.List; uvoz java.util.Neobvezno; javni vmesnik WidgetService {Neobvezno findById (dolg id); Seznam findAll (); Shranjevanje pripomočkov (pripomoček pripomočka); void deleteById (Long id); }

Seznam 2. Razred izvajanja storitve Spring (WidgetServiceImpl.java)

 paket com.geekcap.javaworld.spring5mvcexample.service; uvoz com.geekcap.javaworld.spring5mvcexample.model.Widget; uvoz com.geekcap.javaworld.spring5mvcexample.repository.WidgetRepository; uvoz com.google.common.collect.Lists; uvoz org.springframework.stereotype.Service; uvoz java.util.ArrayList; uvoz java.util.List; uvoz java.util.Neobvezno; @Service javni razred WidgetServiceImpl izvaja WidgetService {zasebno repozitorij WidgetRepository; javni WidgetServiceImpl (repozitorij WidgetRepository) {this.repository = repozitorij; } @Override public Neobvezno findById (Long id) {return repository.findById (id); } @Override javni seznam findAll () {return Lists.newArrayList (repository.findAll ()); } @Override public Widget save (Widget widget) {// Povečajte številko različice widget.setVersion (widget.getVersion () + 1); // Shrani pripomoček v repozitorij return repository.save (widget); } @Override public void deleteById (Long id) {repository.deleteById (id); }}

WidgetServiceImpl je spomladanska storitev, označena z @Service pripis, ki ima a WidgetRepository vanj priključen skozi njegov konstruktor. The findById (), findAll (), in deleteById () metode so vse prehodne metode do osnovnih WidgetRepository. Edina poslovna logika, ki jo boste našli, je v shrani () metoda, ki poveča številko različice datoteke Pripomoček ko je shranjena.

Testni razred

Da bi preizkusili ta razred, moramo ustvariti in konfigurirati model WidgetRepository, ga priklopite na WidgetServiceImpl in nato ožičite WidgetServiceImpl v naš testni razred. Na srečo je to veliko lažje, kot se sliši. Seznam 3 prikazuje izvorno kodo za WidgetServiceTest razred.

Seznam 3. Razred preizkusnega servisnega servisa (WidgetServiceTest.java)

 paket com.geekcap.javaworld.spring5mvcexample.service; uvoz com.geekcap.javaworld.spring5mvcexample.model.Widget; uvoz com.geekcap.javaworld.spring5mvcexample.repository.WidgetRepository; uvoz org.junit.jupiter.api.Trditve; import org.junit.jupiter.api.DisplayName; uvoz org.junit.jupiter.api.Test; uvoz org.junit.jupiter.api.extension.ExtendWith; uvoz org.springframework.beans.factory.annotation.Autowired; uvoz org.springframework.boot.test.context.SpringBootTest; uvoz org.springframework.boot.test.mock.mockito.MockBean; uvoz org.springframework.test.context.junit.jupiter.SpringExtension; uvoz java.util.Arrays; uvoz java.util.List; uvoz java.util.Neobvezno; uvozi statični org.mockito.Mockito.doReturn; uvozi statični org.mockito.ArgumentMatchers.any; @SpringBootTest javni razred WidgetServiceTest {/ ** * Autowire v storitvi, ki jo želimo preizkusiti * / @Autowired zasebna storitev WidgetService; / ** * Ustvari lažno izvedbo WidgetRepository * / @MockBean zasebnega repozitorija WidgetRepository; @Test @DisplayName ("Test findById Success") void testFindById () {// Nastavite naš lažni pripomoček Widget repozitorija = nov Widget (1l, "Ime pripomočka", "Opis", 1); doReturn (Izbirno.of (pripomoček)). when (repozitorij) .findById (1l); // izvedba klica storitve Neobvezno returnWidget = service.findById (1l); // Uveljavi odgovor Assertions.assertTrue (returnWidget.isPresent (), "Pripomočka ni bilo mogoče najti"); Assertions.assertSame (returnWidget.get (), widget, "Vrnjeni gradnik ni bil enak lažnemu besedilu"); } @Test @DisplayName ("Test findById Not Found") void testFindByIdNotFound () {// Nastavite naš lažni repozitorij doReturn (Neobvezno.prazno ()). When (repository) .findById (1l); // izvedba klica storitve Neobvezno returnWidget = service.findById (1l); // Ugotovimo odgovor Assertions.assertFalse (returnWidget.isPresent (), "Pripomočka ne najdem"); } @Test @DisplayName ("Test findAll") void testFindAll () {// Nastavite naš lažni odlagališče Widget widget1 = new Widget (1l, "Widget Name", "Description", 1); Widget widget2 = nov pripomoček (2l, "Ime pripomočka 2", "Opis 2", 4); doReturn (Arrays.asList (widget1, widget2)). when (repozitorij) .findAll (); // Izvedba gradnikov seznama klicev storitve = service.findAll (); // Ugotovimo odgovor Assertions.assertEquals (2, widgets.size (), "findAll naj vrne 2 gradnika"); } @Test @DisplayName ("Preizkusi pripomoček za shranjevanje") void testSave () {// Nastavite naš lažni odlagališče Widget widget = nov pripomoček (1l, "Ime pripomočka", "Opis", 1); doReturn (widget) .when (repozitorij) .save (any ()); // Izvedite pripomoček za servisni klic returnWidget = service.save (pripomoček); // Ugotovimo odgovor Assertions.assertNotNull (returnWidget, "Shranjeni pripomoček ne sme biti nič"); Assertions.assertEquals (2, returnWidget.getVersion (), "Različico je treba povečati"); }} 

The WidgetServiceTest razred je označen z @SpringBootTest pripis, ki skenira ZAPRTI za vse razrede konfiguracije Spring in zrna ter nastavi kontekst aplikacije Spring za preskusni razred. Upoštevajte to WidgetServiceTest tudi implicitno vključuje @ExtendWith (SpringExtension.class) pripis, skozi @SpringBootTest pripis, ki integrira testni razred z JUnit 5.

Testni razred uporablja tudi Spring's @Autowired pripis k samodejni povezavi a WidgetService za testiranje in uporablja Mockito's @MockBean pripomba, da ustvarite lažno WidgetRepository. Na tej točki imamo posmeh WidgetRepository ki ga lahko konfiguriramo in resnično WidgetService s posmehom WidgetRepository priključen vanj.

Testiranje storitve Spring

Prva preskusna metoda, testFindById (), izvrši WidgetServiceje findById () metoda, ki naj vrne Neobvezno ki vsebuje a Pripomoček. Začnemo z ustvarjanjem Pripomoček da želimo WidgetRepository vrniti. Nato uporabimo Mockito API za konfiguracijo WidgetRepository :: findById metoda. Struktura naše lažne logike je naslednja:

 doReturn (VALUE_TO_RETURN) .when (MOCK_CLASS_INSTANCE) .MOCK_METHOD 

V tem primeru pravimo: Vrnite Neobvezno od naših Pripomoček ko je skladišče findById () metoda se pokliče z argumentom 1 (kot a dolga).

Nato pokličemo WidgetServiceje findById z argumentom 1. Nato potrdimo, da je prisoten in da je vrnjen Pripomoček je tista, ki smo jo konfigurirali WidgetRepository vrniti.

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