Skrive maler for testsaker ved bruk av JUnit 5

1. Oversikt

JUnit 5-biblioteket tilbyr mange nye funksjoner i forhold til tidligere versjoner. En slik funksjon er testmaler. Kort sagt er testmaler en kraftig generalisering av JUnit 5s parametrerte og gjentatte tester.

I denne opplæringen skal vi lære hvordan du lager en testmal ved hjelp av JUnit 5.

2. Maven-avhengigheter

La oss begynne med å legge avhengighetene til våre pom.xml.

Vi må legge til hoved-JUnit 5 junit-jupiter-motor avhengighet:

 org.junit.jupiter junit-jupiter-engine 5.7.0 

I tillegg til dette, må vi også legge til junit-jupiter-api avhengighet:

 org.junit.jupiter junit-jupiter-api 5.7.0 

På samme måte kan vi legge til de nødvendige avhengighetene til våre build.gradle fil:

testCompile gruppe: 'org.junit.jupiter', navn: 'junit-jupiter-engine', versjon: '5.7.0' testCompile gruppe: 'org.junit.jupiter', navn: 'junit-jupiter-api', versjon : '5.7.0'

3. Problemstillingen

Før vi ser på testmaler, la oss kort se på JUnit 5s parametrerte tester. Parameteriserte tester tillater oss å injisere forskjellige parametere i testmetoden. Som et resultat, når ved hjelp av parametriserte tester,vi kan utføre en enkelt testmetode flere ganger med forskjellige parametere.

La oss anta at vi nå vil kjøre testmetoden flere ganger - ikke bare med forskjellige parametere, men også under en annen påkallingskontekst hver gang.

Med andre ord, Vi ønsker at testmetoden skal utføres flere ganger, med hver påkallelse ved hjelp av en annen kombinasjon av konfigurasjoner som for eksempel:

  • ved hjelp av forskjellige parametere
  • forberede testklasseinstansen annerledes - det vil si å injisere forskjellige avhengigheter i testinstansen
  • kjører testen under forskjellige forhold, for eksempel å aktivere / deaktivere en delmengde av påkallinger hvis miljøet er “QA
  • kjører med en annen tilbakeringingsatferd for livssyklusen - kanskje vi vil sette opp og rive ned en database før og etter en delmengde av påkallelser

Bruk av parametriserte tester viser seg raskt å være begrenset i dette tilfellet. Heldigvis tilbyr JUnit 5 en kraftig løsning for dette scenariet i form av testmaler.

4. Testmaler

Testmaler i seg selv er ikke testtilfeller. I stedet, som navnet antyder, er de bare maler for gitte testsaker. De er en kraftig generalisering av parametriserte og gjentatte tester.

Testmaler påkalles en gang for hver påkallingskontekst gitt av leverandøren (e) av påkallelseskonteksten.

La oss nå se på et eksempel på testmalene. Som vi etablerte ovenfor, er hovedaktørene:

  • en testmålmetode
  • en testmalmetode
  • en eller flere tilbydere av kontekstleverandører registrert med malmetoden
  • en eller flere anropskontekster gitt av hver leverandør av anropskontekst

4.1. Testmålmetoden

For dette eksemplet skal vi bruke en enkel UserIdGeneratorImpl.generert metode som vårt testmål.

La oss definere UserIdGeneratorImpl klasse:

offentlig klasse UserIdGeneratorImpl implementerer UserIdGenerator {privat boolsk isFeatureEnabled; offentlig UserIdGeneratorImpl (boolsk isFeatureEnabled) {this.isFeatureEnabled = isFeatureEnabled; } offentlig streng generere (streng fornavn, streng etternavn) {streng initialAndLastName = fornavn.substring (0, 1) .concat (etternavn); return isFeatureEnabled? "bael" .concat (initialAndLastName): initialAndLastName; }}

De generere metoden, som er vårt testmål, tar fornavn og etternavn som parametere og genererer en bruker-ID. Bruker-ID-ens format varierer, avhengig av om en funksjonsbryter er aktivert eller ikke.

La oss se hvordan dette ser ut:

Bryter for gitt funksjon er deaktivert Når fornavn = "John" og etternavn = "Smith" Da returneres "JSmith" Gitt funksjonsbryter er aktivert Når fornavn = "John" og etternavn = "Smith" Da returneres "baelJSmith"

Deretter la oss skrive testmalmetoden.

4.2. Testmalmetoden

Her er en testmal for vår testmålmetode UserIdGeneratorImpl.generert:

offentlig klasse UserIdGeneratorImplUnitTest {@TestTemplate @ExtendWith (UserIdGeneratorTestInvocationContextProvider.class) offentlig ugyldig nårUserIdRequested_thenUserIdIsReturnedInCorrectFormat (UserIdGeneratorTestCase testGenerator) UserIdentatorGenerator (UserIdGenerator) UserIdGenerator (UserIdGeneratorTestCase testGenerator) {UserIdGenerator = UserGenerator) Streng actualUserId = userIdGenerator.generate (testCase.getFirstName (), testCase.getLastName ()); assertThat (actualUserId) .isEqualTo (testCase.getExpectedUserId ()); }}

La oss se nærmere på testmalmetoden.

Til å begynne med, vi lager vår testmalmetode ved å merke den med JUnit 5 @TestTemplate kommentar.

Følger det, registrerer vi en kontekstleverandør, UserIdGeneratorTestInvocationContextProvider,bruker @ExtendWith kommentar. Vi kan registrere flere kontekstleverandører med testmalen. For formålet med dette eksemplet registrerer vi imidlertid en enkelt leverandør.

Malmetoden mottar også en forekomst av UserIdGeneratorTestCase som parameter. Dette er ganske enkelt en innpakningsklasse for inngangene og det forventede resultatet av testsaken:

offentlig klasse UserIdGeneratorTestCase {private boolean isFeatureEnabled; privat streng fornavn; privat streng etternavn; privat streng forventet brukerbruker; // Standard settere og getters}

Til slutt påkaller vi testmålmetoden og hevder at resultatet er som forventet

Nå er det på tide å definere vår leverandør av anropskontekst.

4.3. Innkallingskontekstleverandøren

Vi må registrere minst en TestTemplateInvocationContextProvider med testmalen vår. Hver registrert TestTemplateInvocationContextProvider gir en Strøm av TestTemplateInvocationContext tilfeller.

Tidligere brukte du @ExtendWith kommentar, vi registrerte UserIdGeneratorTestInvocationContextProvider som vår anropsleverandør.

La oss definere denne klassen nå:

offentlig klasse UserIdGeneratorTestInvocationContextProvider implementerer TestTemplateInvocationContextProvider {// ...}

Vår påkallelsessammenheng implementerer TestTemplateInvocationContextProvider grensesnitt, som har to metoder:

  • støtter TestTemplate
  • provideTestTemplateInvocationContexts

La oss starte med å implementere støtter TestTemplate metode:

@Override public boolean supportsTestTemplate (ExtensionContext extensionContext) {return true; }

Utførelsesmotoren JUnit 5 kaller støtter TestTemplate metoden først for å validere om leverandøren gjelder for det gitte ExecutionContext. I dette tilfellet kommer vi rett og slett tilbake ekte.

La oss nå implementere provideTestTemplateInvocationContexts metode:

@Override public Stream supplyTestTemplateInvocationContexts (ExtensionContext extensionContext) {boolean featureDisabled = false; boolsk featureEnabled = true; return Stream.of (featureDisabledContext (new UserIdGeneratorTestCase ("Gitt funksjonsbryter deaktivert Når brukernavn er John Smith. Så generert userid er JSmith", featureDisabled, "John", "Smith", "JSmith")), featureEnabledContext (ny UserIdGeneratorTestCase (" Gitt funksjonsbryter aktivert Når brukernavn er John Smith Da er generert brukerid baelJSmith ", featureEnabled," John "," Smith "," baelJSmith "))); }

Formålet med provideTestTemplateInvocationContexts metoden er å gi en Strøm av TestTemplateInvocationContext tilfeller. For vårt eksempel returnerer den to forekomster, gitt av metodene featureDisabledContext og featureEnabledContext. Derfor vil testmalen vår kjøre to ganger.

La oss se på de to TestTemplateInvocationContext tilfeller som returneres etter disse metodene.

4.4. Innkallingskontekstforekomster

Påkallingskontekstene er implementeringer av TestTemplateInvocationContext grensesnitt og implementere følgende metoder:

  • getDisplayName - gi et testvisningnavn
  • getAdditionalExtensions - returnere tilleggsutvidelser for anropssammenheng

La oss definere featureDisabledContext metode som returnerer vår første anropssammenheng:

privat TestTemplateInvocationContext featureDisabledContext (UserIdGeneratorTestCase userIdGeneratorTestCase) {return new TestTemplateInvocationContext () {@Override public String getDisplayName (int invocationIndex) {return userIdGeneratorTestCase.getDisplayName (); } @Override public List getAdditionalExtensions () {return asList (new GenericTypedParameterResolver (userIdGeneratorTestCase), new BeforeTestExecutionCallback () {@Override public void beforeTestExecution (ExtensionContext extensionContext) {System.out.printlecution ("Before) ny AfterTestExecutionCallback () {@Override public void afterTestExecution (ExtensionContext extensionContext) {System.out.println ("AfterTestExecutionCallback: Disabled context");}}); }}; }

For det første for påkallingssammenheng returnert av featureDisabledContext metoden, er utvidelsene vi registrerer:

  • GenericTypedParameterResolver - en parameter resolver utvidelse
  • BeforeTestExecutionCallback - en tilbakeringingstid for livssyklus som kjører umiddelbart før testutførelsen
  • AfterTestExecutionCallback - en tilbakeringingstid for livssyklus som kjører umiddelbart etter testutførelsen

Imidlertid, for den andre anropskonteksten, returnert av featureEnabledContext metode, la oss registrere et annet sett med utvidelser (beholde GenericTypedParameterResolver):

privat TestTemplateInvocationContext-funksjonEnabledContext (UserIdGeneratorTestCase userIdGeneratorTestCase) {returner ny TestTemplateInvocationContext () {@ Override public String getDisplayName (int invocationIndex) {return userIdGeneratorTestCase.getDisplayName (); } @Override public List getAdditionalExtensions () {return asList (new GenericTypedParameterResolver (userIdGeneratorTestCase), new DisabledOnQAEnvironmentExtension (), new BeforeEachCallback () {@ Override public void beforeEach (ExtensionContext extensionContext): contextContext );}}, ny AfterEachCallback () {@Override public void afterEach (ExtensionContext extensionContext) {System.out.println ("AfterEachCallback: Enabled context");}}); }}; }

For den andre anropskonteksten er utvidelsene vi registrerer:

  • GenericTypedParameterResolver - en parameter resolver utvidelse
  • DisabledOnQAEnvironmentExtension - en utførelsesbetingelse for å deaktivere testen hvis miljøegenskapen (lastet fra application.properties fil) er “qa
  • BeforeEachCallback - en tilbakeringingsutvidelse for livssyklusen som kjører før hver testmetode kjøres
  • AfterEachCallback - en tilbakeringingstid for livssyklus som kjøres etter hver kjøring av testmetoden

Fra eksemplet ovenfor er det klart å se at:

  • den samme testmetoden kjøres under flere anropskontekster
  • hver påkallingskontekst bruker sitt eget sett med utvidelser som skiller seg både i antall og natur fra utvidelsene i andre påkallingskontekster

Som et resultat kan en testmetode påberopes flere ganger under en helt annen påkallingskontekst hver gang. Og ved å registrere flere kontekstleverandører, kan vi tilby enda flere lag med påkallingskontekster der vi kan kjøre testen.

5. Konklusjon

I denne artikkelen så vi på hvordan JUnit 5s testmaler er en kraftig generalisering av parametrerte og gjentatte tester.

Til å begynne med så vi på noen begrensninger i de parametriserte testene. Deretter diskuterte vi hvordan testmaler overvinne begrensningene ved å la en test kjøres under en annen kontekst for hver påkalling.

Til slutt så vi på et eksempel på å lage en ny testmal. Vi brøt eksemplet for å forstå hvordan maler fungerer sammen med leverandører av påkallelseskontekster og påkallingskontekster.

Som alltid er kildekoden for eksemplene som brukes i denne artikkelen tilgjengelig på GitHub.


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