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 HainesKaj 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 WidgetService
je 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 WidgetService
je findById
z argumentom 1. Nato potrdimo, da je prisoten in da je vrnjen Pripomoček
je tista, ki smo jo konfigurirali WidgetRepository
vrniti.