Eenheid testen unit-testing
Dit leerprogramma behandelt de implementatie van een eenheidstest die het gedrag van het het Schuiven Model van de component van de Byline bevestigt, dat in het 🔗 leerprogramma van de Component van de 0} Douane {wordt gecreeerd.
Vereisten prerequisites
Herzie het vereiste tooling en de instructies voor vestiging a lokale ontwikkelomgeving.
als zowel Java™ 8 als Java™ 11 op het systeem geïnstalleerd zijn, kan de de testlooper van de Code van VS lagere runtime van Java™ selecteren wanneer het uitvoeren van de tests, resulterend in testmislukkingen. Als dit voorkomt, desinstalleer Java™ 8.
Starter-project
Bekijk de basislijncode waarop de zelfstudie is gebaseerd:
-
Controle uit de
tutorial/unit-testing-start
tak van GitHubcode language-shell $ cd aem-guides-wknd $ git checkout tutorial/unit-testing-start
-
Stel codebasis aan een lokale AEM instantie op gebruikend uw Maven vaardigheden:
code language-shell $ mvn clean install -PautoInstallSinglePackage
note note NOTE Als u AEM 6.5 of 6.4 gebruikt, voegt u het classic
-profiel toe aan Maven-opdrachten.code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
U kunt de gebeëindigde code op GitHubaltijd bekijken of de code plaatselijk controleren door aan de tak tutorial/unit-testing-start
te schakelen.
Doelstelling
- Begrijp de grondbeginselen van eenheidstests.
- Leer over kaders en hulpmiddelen algemeen worden gebruikt om AEM code te testen die.
- Begrijp opties voor het verplaatsen of simuleren van AEM middelen wanneer het schrijven van eenheidstests.
Achtergrond unit-testing-background
In dit leerprogramma, zullen wij onderzoeken hoe te om Tests van de Eenheidvoor 2} Sling Model van onze component Byline 🔗 te schrijven (gecreeerd in Creërend een douane AEM Component). Eenheidstests zijn in Java™ geschreven ontwikkeltijdstests die het verwachte gedrag van Java™-code controleren. Elke eenheidstest is doorgaans klein en valideert de uitvoer van een methode (of werkeenheden) aan de hand van de verwachte resultaten.
We gebruiken AEM best practices en gebruiken:
Unit Testing and Adobe Cloud Manager unit-testing-and-adobe-cloud-manager
Adobe Cloud Managerintegreert de uitvoering van de eenheidstest en codedekking rapporterendin zijn pijpleiding CI/CD helpen de beste praktijken van eenheid het testen AEM code aanmoedigen en bevorderen.
Hoewel het testen van eenheden een goede praktijk voor om het even welke codebasis is, is het belangrijk om bij het gebruiken van Cloud Manager uit zijn het testen en rapporteringsfaciliteiten van de codekwaliteit voordeel te halen door eenheidstests voor Cloud Manager te verstrekken om te lopen.
Werk de test Geweven gebiedsdelen bij inspect-the-test-maven-dependencies
De eerste stap is Geweven gebiedsdelen te inspecteren om het schrijven en het runnen van de tests te steunen. Er zijn vier vereiste afhankelijkheden:
- JUnit5
- Mockito Test Framework
- Apache Sling Mocks
- AEM Mocks Test Framework (per io.wcm)
JUnit5, Mockito, en ​ AEM de testgebiedsdelen** automatisch toegevoegd aan het project tijdens opstelling gebruikend AEM Maven archetype.
-
Om deze gebiedsdelen te bekijken, open POM van de Bovenliggende Reactor in aem-guides-wknd/pom.xml, navigeer aan
<dependencies>..</dependencies>
en bekijk de gebiedsdelen voor JUnit, Mockito, Apache Sling Mocks, en AEM de Tests van het Mock door io.wcm onder<!-- Testing -->
. -
Zorg ervoor dat
io.wcm.testing.aem-mock.junit5
aan 4.1.0 wordt geplaatst:code language-xml <dependency> <groupId>io.wcm</groupId> <artifactId>io.wcm.testing.aem-mock.junit5</artifactId> <version>4.1.0</version> <scope>test</scope> </dependency>
note caution CAUTION Archetype 35 produceert het project met io.wcm.testing.aem-mock.junit5
versie 4.1.8. Gelieve te degraderen aan 4.1.0 om de rest van dit hoofdstuk te volgen. -
Open aem-guides-wknd/core/pom.xml en mening dat de overeenkomstige het testen gebiedsdelen beschikbaar zijn.
Een parallelle bronomslag in het kern project zal de eenheidstests en om het even welke ondersteunende testdossiers bevatten. Deze test omslag verstrekt scheiding van testklassen van de broncode maar staat de tests toe om te handelen alsof zij in de zelfde pakketten zoals de broncode leven.
De JUnit-test maken creating-the-junit-test
De tests van de eenheid brengen typisch 1-aan-1 met klassen Javaâ„¢ in kaart. In dit hoofdstuk, zullen wij een test JUnit voor BylineImpl.java schrijven, die het het Verlenen Model is dat de component van de Naamregel steunt.
Plaats waar de tests van de Eenheid worden opgeslagen.
-
Maak een eenheidstest voor de
BylineImpl.java
door een nieuwe Javaâ„¢-klasse ondersrc/test/java
te maken in een Javaâ„¢-pakketmapstructuur die de locatie van de te testen Javaâ„¢-klasse weerspiegelt.Aangezien we testen
src/main/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImpl.java
een overeenkomende eenheidstest voor een Javaâ„¢-klasse maken op
src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
Het achtervoegsel
Test
in het testbestand voor eenheden,BylineImplTest.java
, is een conventie, waarmee we- Identificeer het gemakkelijk als testdossier voor
BylineImpl.java
- Maar ook, onderscheidt het testdossier van de klasse die wordt getest,
BylineImpl.java
BylineImplTest.java evalueren reviewing-bylineimpltest-java
Het JUnit-testbestand is nu een lege Javaâ„¢-klasse.
-
Werk het bestand bij met de volgende code:
code language-java package com.adobe.aem.guides.wknd.core.models.impl; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class BylineImplTest { @BeforeEach void setUp() throws Exception { } @Test void testGetName() { fail("Not yet implemented"); } @Test void testGetOccupations() { fail("Not yet implemented"); } @Test void testIsEmpty() { fail("Not yet implemented"); } }
-
De eerste methode
public void setUp() { .. }
wordt voorzien van een annotatie met JUnit@BeforeEach
, die de JUnit-testruntime de instructie geeft deze methode uit te voeren voordat elke testmethode in deze klasse wordt uitgevoerd. Dit verstrekt een handige plaats om gemeenschappelijke het testen staat te initialiseren die door alle tests wordt vereist. -
De volgende methoden zijn de testmethoden, waarvan de namen worden voorafgegaan door
test
volgens conventie en worden gemarkeerd met de@Test
-annotatie. U ziet dat al onze tests standaard mislukken, omdat we ze nog niet hebben uitgevoerd.Om te beginnen, beginnen wij met één enkele testmethode voor elke openbare methode op de klasse wij testen, zo:
table 0-row-3 1-row-3 2-row-3 3-row-3 BylineImpl.java BylineImplTest.java getName() wordt getest door testGetName() getOccupations() wordt getest door testGetOccupations() isEmpty() wordt getest door testIsEmpty() Deze methoden kunnen zo nodig worden uitgebreid, zoals verderop in dit hoofdstuk wordt weergegeven.
Wanneer deze JUnit-testklasse (ook wel JUnit Test Case genoemd) wordt uitgevoerd, wordt elke met
@Test
gemarkeerde methode uitgevoerd als een test die kan slagen of afbreken.
core/src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
-
Stel het Geval van de Test JUnit in werking door op het
BylineImplTest.java
dossier met de rechtermuisknop te klikken, en het tikken Looppas.
Zoals verwacht, mislukken alle tests, omdat ze nog niet zijn uitgevoerd.klik op BylineImplTests.java met de rechtermuisknop aan > Looppas
BylineImpl.java evalueren reviewing-bylineimpl-java
Bij het schrijven van eenheidstests zijn er twee primaire benaderingen:
- TDD of de Gedreven Ontwikkeling van de Test, die impliceert het schrijven van de eenheidstests incrementeel, onmiddellijk alvorens de implementatie wordt ontwikkeld; schrijf een test, schrijf de implementatie om de testpas te maken.
- Implementatie-eerste Ontwikkeling, die het ontwikkelen van werkende code eerst en dan het schrijven tests impliceert die genoemde code bevestigen.
In dit leerprogramma, wordt de laatstgenoemde benadering gebruikt (aangezien wij reeds een werkende BylineImpl.java in een vorig hoofdstuk hebben gecreeerd). Daarom moeten we het gedrag van de openbare methoden van het systeem, maar ook een aantal van de toepassingsdetails ervan, herzien en begrijpen. Dit kan tegendeel klinken, aangezien een goede test alleen de inputs en outputs moet betreffen, maar wanneer men in AEM werkt, zijn er verschillende implementatieoverwegingen die moeten worden begrepen om werktests te kunnen uitvoeren.
TDD in de context van AEM vereist een niveau van deskundigheid en kan het best worden aangenomen door AEM ontwikkelaars die deskundig zijn in AEM ontwikkeling en eenheidstests van AEM code.
Opzetten AEM testcontext setting-up-aem-test-context
De meeste code die voor AEM wordt geschreven, is afhankelijk van API's van het type JCR, Sling of AEM. Deze API's vereisen dat de context van een actieve AEM correct wordt uitgevoerd.
Aangezien de eenheidstests bij bouwstijl, buiten de context van een lopende AEM instantie worden uitgevoerd, is er geen dergelijke context. Om dit te vergemakkelijken, AEM Mocks van wcm.iocreeert mock context die deze APIs __ toestaat dienst alsof zij in AEM lopen.
-
Creeer een AEM context gebruikend wcm.io
AemContext
in BylineImplTest.java door het toe te voegen als uitbreiding JUnit die met@ExtendWith
aan het { dossier 6} wordt versierd BylineImplTest.java. ​ ​De extensie zorgt voor alle vereiste initialisatie- en opschoningstaken. Maak een klassevariabele voorAemContext
die voor alle testmethoden kan worden gebruikt.code language-java import org.junit.jupiter.api.extension.ExtendWith; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; ... @ExtendWith(AemContextExtension.class) class BylineImplTest { private final AemContext ctx = new AemContext();
Met deze variabele,
ctx
, wordt een AEM context belicht die enkele AEM- en Sling-abstracties biedt:- Het BylineImpl-opmaakmodel is in deze context geregistreerd
- In deze context worden structuur voor JCR-inhoud van Mock gemaakt
- Aangepaste OSGi-services kunnen in deze context worden geregistreerd
- Verschillende veelvoorkomende vereiste modelobjecten en hulpelementen, zoals SlingHttpServletRequest-objecten, diverse services voor modelschaling en AEM OSGi, zoals ModelFactory, PageManager, Page, Template, ComponentManager, Component, TagManager, Tag, enzovoort.
- niet alle methodes voor deze voorwerpen worden uitgevoerd!
- En veel meer!
Het
ctx
-object fungeert als ingangspunt voor het grootste deel van onze modelcontext. -
Definieer in de methode
setUp(..)
, die wordt uitgevoerd vóór elke methode@Test
, een algemene status voor het testen van modellen:code language-java @BeforeEach public void setUp() throws Exception { ctx.addModelsForClasses(BylineImpl.class); ctx.load().json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content"); }
addModelsForClasses
registreert het te testen Sling Model, in de mock AEM Context, zodat kan het in de@Test
methodes worden geconcretiseerd.load().json
laadt bronstructuren in de modelcontext, die de code toestaat om met deze middelen in wisselwerking te staan alsof zij door een echte bewaarplaats werden verstrekt. De middeldefinities in het dossierBylineImplTest.json
worden geladen in de mockJCR context onder /content.BylineImplTest.json
bestaat nog niet, dus laten we het maken en de JCR-bronstructuren definiëren die nodig zijn voor de test.
-
De JSON- dossiers die de modelmiddelstructuren vertegenwoordigen worden opgeslagen onder kern/src/test/resources na het zelfde pakket dat als JUnit Javaâ„¢ testdossier plakt.
Creeer een JSON- dossier bij
core/test/resources/com/adobe/aem/guides/wknd/core/models/impl
genoemd BylineImplTest.json met de volgende inhoud:code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline" } }
Deze JSON definieert een modelbron (JCR-knooppunt) voor de eenheidstest van de Byline-component. Op dit punt heeft de JSON de minimale set eigenschappen die vereist is om een inhoudsbron van een component Byline, de
jcr:primaryType
ensling:resourceType
, te vertegenwoordigen.Een algemene regel bij het werken met eenheidstests is het maken van de minimale set met mock-inhoud, -context en -code die nodig is om aan elke test te voldoen. Vermijd de verleiding om een complete mock-context op te bouwen voordat de tests worden geschreven, aangezien dit vaak tot ongewenste artefacten leidt.
Nu met het bestaan van BylineImplTest.json, wanneer
ctx.json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content")
wordt uitgevoerd, worden de modelmiddeldefinities geladen in de context bij de weg /content.
getName() testen testing-get-name
Nu wij een basismodelcontextopstelling hebben, schrijven wij onze eerste test voor BylineImpl getName (). Deze test moet de methode getName () verzekeren keert de correct-geschreven naam terug die bij het 2} wordt opgeslagen naam van het middel "bezit.
-
Werk testGetName () methode in BylineImplTest.java als volgt bij:
code language-java import com.adobe.aem.guides.wknd.core.models.Byline; ... @Test public void testGetName() { final String expected = "Jane Doe"; ctx.currentResource("/content/byline"); Byline byline = ctx.request().adaptTo(Byline.class); String actual = byline.getName(); assertEquals(expected, actual); }
String expected
stelt de verwachte waarde in. Wij zullen dit aan "Gedaan Jane plaatsen.ctx.currentResource
plaatst de context van het modelmiddel om de code tegen te evalueren, zodat wordt dit geplaatst aan /content/byline aangezien dat is waar de bron van de modelinhoud wordt geladen.Byline byline
instantieert het Byline Sling Model door het van het modelvoorwerp van het Verzoek aan te passen.String actual
roept de methode aan die we testen,getName()
, op het Byline Sling Model-object.assertEquals
geeft aan dat de verwachte waarde overeenkomt met de waarde die wordt geretourneerd door het byline Sling Model-object. Als deze waarden niet gelijk zijn, zal de test mislukken.
-
Voer de test uit… en deze mislukt met een
NullPointerException
.Deze test mislukt NIET omdat we nooit een eigenschap
name
hebben gedefinieerd in de mock JSON, waardoor de test mislukt, maar de uitvoering van de test is op dat punt niet gekomen! Deze test mislukt als gevolg van eenNullPointerException
op het byline-object zelf. -
Als
@PostConstruct init()
inBylineImpl.java
een uitzondering genereert, voorkomt dit dat het Sling Model wordt geïnstantieerd en wordt de waarde van dat Sling Model-object null.code language-java @PostConstruct private void init() { image = modelFactory.getModelFromWrappedRequest(request, request.getResource(), Image.class); }
Hoewel de OSGi-service ModelFactory via
AemContext
(als Apache Sling-context) wordt aangeboden, worden niet alle methoden geïmplementeerd, inclusiefgetModelFromWrappedRequest(...)
die in de BylineImpl-methodeinit()
wordt aangeroepen. Dit resulteert in een AbstractMethodError, die in termijninit()
om veroorzaakt te ontbreken, en de resulterende aanpassing vanctx.request().adaptTo(Byline.class)
is een ongeldig voorwerp.Aangezien de geleverde modellen onze code niet kunnen aanpassen, moeten wij de modelcontext zelf uitvoeren voor dit, kunnen wij Mockito gebruiken om een modelvoorwerp te creëren ModelFactory, dat een modelvoorwerp van het Beeld terugkeert wanneer
getModelFromWrappedRequest(...)
op het wordt aangehaald.Omdat deze modelcontext aanwezig moet zijn om zelfs maar een instantie van het Byline Sling-model te kunnen maken, kunnen we deze toevoegen aan de methode
@Before setUp()
. Wij moeten ookMockitoExtension.class
aan de@ExtendWith
annotation boven de BylineImplTest klasse toevoegen.code language-java package com.adobe.aem.guides.wknd.core.models.impl; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.Mock; import com.adobe.aem.guides.wknd.core.models.Byline; import com.adobe.cq.wcm.core.components.models.Image; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; import org.apache.sling.models.factory.ModelFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.apache.sling.api.resource.Resource; @ExtendWith({ AemContextExtension.class, MockitoExtension.class }) public class BylineImplTest { private final AemContext ctx = new AemContext(); @Mock private Image image; @Mock private ModelFactory modelFactory; @BeforeEach public void setUp() throws Exception { ctx.addModelsForClasses(BylineImpl.class); ctx.load().json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content"); lenient().when(modelFactory.getModelFromWrappedRequest(eq(ctx.request()), any(Resource.class), eq(Image.class))) .thenReturn(image); ctx.registerService(ModelFactory.class, modelFactory, org.osgi.framework.Constants.SERVICE_RANKING, Integer.MAX_VALUE); } @Test void testGetName() { ... }
@ExtendWith({AemContextExtension.class, MockitoExtension.class})
merkt de klasse van het Geval van de Test die met de Uitbreiding Jupiter van het Mockito JUnitmoet worden in werking gesteld die voor het gebruik van de @Mock annotaties toestaat om mock voorwerpen op het niveau van de Klasse te bepalen.@Mock private Image
maakt een mock-object van het typecom.adobe.cq.wcm.core.components.models.Image
. Dit is gedefinieerd op klasseniveau, zodat@Test
-methoden zo nodig hun gedrag kunnen wijzigen.@Mock private ModelFactory
maakt een modelobject van het type ModelFactory. Dit is een puur Mockito-mock en er zijn geen methoden op toegepast. Dit wordt bepaald op het klassenniveau zodat, zoals nodig,@Test
de methodes zijn gedrag kunnen veranderen zoals nodig.when(modelFactory.getModelFromWrappedRequest(..)
registreert het modelgedrag voor wanneergetModelFromWrappedRequest(..)
wordt aangeroepen voor het modelobject ModelFactory. Het resultaat dat inthenReturn (..)
wordt gedefinieerd, is het retourneren van het modelafbeeldingsobject. Dit gedrag wordt alleen aangeroepen wanneer: de eerste parameter is gelijk aan het request-object vanctx
, de tweede parameter een Resource-object is en de derde parameter de Core Components Image-klasse moet zijn. Wij aanvaarden om het even welk Middel omdat door onze tests wijctx.currentResource(...)
aan diverse modelmiddelen plaatsen die in worden bepaald BylineImplTest.json. Merk op dat wij lenient () strengheid toevoegen omdat wij later dit gedrag van ModelFactory zullen willen met voeten treden.ctx.registerService(..)
. registreert het modelobject ModelFactory in AemContext, met de hoogste de dienstrangschikking. Dit is vereist omdat de ModelFactory die in BylineImplinit()
wordt gebruikt via het@OSGiService ModelFactory model
gebied wordt ingespoten. Voor AemContext om ons modelvoorwerp te injecteren, dat vraag aangetModelFromWrappedRequest(..)
behandelt, moeten wij het als hoogste rangschikkende Dienst van dat type (ModelFactory) registreren.
-
Voer de test opnieuw uit, en nogmaals, het mislukt, maar dit keer is de boodschap duidelijk waarom de test is mislukt.
testGetName () mislukking toe te schrijven aan bewering
Wij ontvangen een AssertionError wat de bevestigingsvoorwaarde in de ontbroken test betekent, en het vertelt ons de verwachte waarde is "Jansen" maar de daadwerkelijke waarde is ongeldig. Dit maakt steek omdat het "naam" bezit niet aan mock /content/byline middeldefinitie in BylineImplTest.json is toegevoegd, zo laat het toevoegen:
-
Update BylineImplTest.json om te bepalen
"name": "Jane Doe".
code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe" } }
-
Voer de test opnieuw uit en
testGetName()
gaat nu door!
getOccupations() testen testing-get-occupations
Ok, geweldig! De eerste test is geslaagd! Laten we verder gaan en getOccupations()
testen. Aangezien de initialisatie van de modelcontext in de @Before setUp()
methode werd gedaan, is dit beschikbaar aan alle @Test
methodes in dit Geval van de Test, met inbegrip van getOccupations()
.
Onthoud dat deze methode een alfabetisch gesorteerde lijst met beroepen (aflopend) moet retourneren die is opgeslagen in de eigenschap bezettingen.
-
testGetOccupations()
als volgt bijwerken:code language-java import java.util.List; import com.google.common.collect.ImmutableList; ... @Test public void testGetOccupations() { List<String> expected = new ImmutableList.Builder<String>() .add("Blogger") .add("Photographer") .add("YouTuber") .build(); ctx.currentResource("/content/byline"); Byline byline = ctx.request().adaptTo(Byline.class); List<String> actual = byline.getOccupations(); assertEquals(expected, actual); }
List<String> expected
definieert het verwachte resultaat.ctx.currentResource
plaatst het huidige middel om de context tegen de modelmiddeldefinitie bij /content/byline te evalueren. Dit verzekert BylineImpl.java in de context van ons modelmiddel uitvoert.ctx.request().adaptTo(Byline.class)
instantieert het Byline Sling Model door het van het modelvoorwerp van het Verzoek aan te passen.byline.getOccupations()
roept de methode aan die we testen,getOccupations()
, op het Byline Sling Model-object.assertEquals(expected, actual)
beweert dat de verwachte lijst gelijk is aan de werkelijke lijst.
-
Herinner me, enkel als
getName()
hierboven, BylineImplTest.json geen beroepen bepaalt, zodat zal deze test ontbreken als wij het in werking stellen, aangezienbyline.getOccupations()
een lege lijst zal terugkeren.Werk BylineImplTest.json bij om een lijst van beroepen te omvatten, en zij worden geplaatst in niet alfabetische orde om ervoor te zorgen dat onze tests bevestigen dat de beroepen alfabetisch door
getOccupations()
worden gesorteerd.code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe", "occupations": ["Photographer", "Blogger", "YouTuber"] } }
-
Voer de test uit, en nogmaals, we slagen! Het lijkt alsof de gesorteerde beroepen werken!
testGetOccupations () gaat over
Testing isEmpty() testing-is-empty
De laatste methode om isEmpty()
te testen.
Het testen isEmpty()
is interessant omdat het testen op verschillende voorwaarden vereist. Het herzien van BylineImpl.java isEmpty()
methode de volgende voorwaarden moeten worden getest:
- Retourneer true wanneer de naam leeg is
- Retourneer true wanneer de bezettingen null of leeg zijn
- Retourneer true wanneer de afbeelding null is of geen src-URL heeft
- Retourneer false wanneer de naam, de bezetting en de afbeelding (met een URL voor de bron) aanwezig zijn
Hiervoor moeten we testmethoden maken, waarbij elke test een specifieke voorwaarde en nieuwe modelbronstructuren in BylineImplTest.json
test om deze tests te starten.
Met deze controle konden we het testen overslaan als getName()
, getOccupations()
en getImage()
leeg zijn, omdat het verwachte gedrag van die status via isEmpty()
wordt getest.
-
De eerste test zal de voorwaarde van een gloednieuwe component testen, die geen eigenschappen heeft geplaatst.
Voeg een nieuwe middeldefinitie aan
BylineImplTest.json
toe, die het de semantische naam "leeg geeft"code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe", "occupations": ["Photographer", "Blogger", "YouTuber"] }, "empty": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline" } }
"empty": {...}
definieert een nieuwe brondefinitie met de naam 'empty' die alleen eenjcr:primaryType
ensling:resourceType
heeft.Vergeet niet dat we
BylineImplTest.json
inctx
laden voordat elke testmethode in@setUp
wordt uitgevoerd. Deze nieuwe brondefinitie is dus direct beschikbaar voor ons in tests op /content/empty. -
Werk
testIsEmpty()
als volgt bij, plaatsend het huidige middel aan nieuwe "lege"modelmiddeldefinitie.code language-java @Test public void testIsEmpty() { ctx.currentResource("/content/empty"); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); }
Voer de test uit en controleer of deze slaagt.
-
Maak vervolgens een set methoden om ervoor te zorgen dat
isEmpty()
true retourneert wanneer een van de vereiste gegevenspunten (naam, bezinking of afbeelding) leeg is.Voor elke test, wordt een discrete modelmiddeldefinitie gebruikt, update BylineImplTest.json met de extra middeldefinities voor zonder-naam en zonder-bezettingen.
code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe", "occupations": ["Photographer", "Blogger", "YouTuber"] }, "empty": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline" }, "without-name": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "occupations": "[Photographer, Blogger, YouTuber]" }, "without-occupations": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe" } }
Maak de volgende testmethoden om deze statussen te testen.
code language-java @Test public void testIsEmpty() { ctx.currentResource("/content/empty"); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); } @Test public void testIsEmpty_WithoutName() { ctx.currentResource("/content/without-name"); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); } @Test public void testIsEmpty_WithoutOccupations() { ctx.currentResource("/content/without-occupations"); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); } @Test public void testIsEmpty_WithoutImage() { ctx.currentResource("/content/byline"); lenient().when(modelFactory.getModelFromWrappedRequest(eq(ctx.request()), any(Resource.class), eq(Image.class))).thenReturn(null); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); } @Test public void testIsEmpty_WithoutImageSrc() { ctx.currentResource("/content/byline"); when(image.getSrc()).thenReturn(""); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); }
testIsEmpty()
test de lege modelbrondefinitie en stelt datisEmpty()
waar is.testIsEmpty_WithoutName()
test op een modelbrondefinitie die beroepen maar geen naam heeft.testIsEmpty_WithoutOccupations()
test tegen een modelbrondefinitie die een naam maar geen beroepen heeft.testIsEmpty_WithoutImage()
test tegen een mock middeldefinitie met een naam en bezinkingen maar plaatst het mockBeeld om aan ongeldig terug te keren. Merk op dat wij hetmodelFactory.getModelFromWrappedRequest(..)
gedrag met voeten willen treden dat insetUp()
wordt bepaald om het voorwerp van het Beeld te verzekeren door deze vraag is teruggekeerd ongeldig is. De functie Mockito-stubs is strikt en wil geen dubbele code. Daarom stellen we het model metlenient
-instellingen zo in dat expliciet wordt aangegeven dat we het gedrag in de methodesetUp()
overschrijven.testIsEmpty_WithoutImageSrc()
test een modelbrondefinitie met een naam en een bezigheid, maar plaatst het modelBeeld om een leeg koord terug te keren wanneergetSrc()
wordt aangehaald. -
Tot slot schrijf een test om ervoor te zorgen dat isEmpty () vals terugkeert wanneer de component behoorlijk wordt gevormd. Voor deze voorwaarde, kunnen wij opnieuw gebruiken/content/byline die een volledig gevormde component van de Byline vertegenwoordigt.
code language-java @Test public void testIsNotEmpty() { ctx.currentResource("/content/byline"); when(image.getSrc()).thenReturn("/content/bio.png"); Byline byline = ctx.request().adaptTo(Byline.class); assertFalse(byline.isEmpty()); }
-
Voer nu alle eenheidstests in het bestand BylineImplTest.java uit en bekijk de uitvoer van het Javaâ„¢-testrapport.
Tests van de eenheid als onderdeel van de constructie running-unit-tests-as-part-of-the-build
Eenheidstests worden uitgevoerd en moeten als onderdeel van de gefabriceerde build slagen. Dit zorgt ervoor dat alle tests met succes overgaan alvorens een toepassing wordt opgesteld. Het uitvoeren van Gemaakte doelstellingen zoals pakket of installeert roept automatisch en vereist de overgaan van alle eenheidstests in het project.
$ mvn package
$ mvn package
Op dezelfde manier, als wij een testmethode veranderen om te ontbreken, ontbreekt de bouwstijl en rapporten die test ontbrak en waarom.
De code controleren review-the-code
Bekijk de gebeëindigde code op GitHubof herzie en stel plaatselijk de code bij de tak van het Git tutorial/unit-testing-solution
op.