Enhetstestning unit-testing
I den här självstudiekursen beskrivs implementeringen av ett enhetstest som validerar beteendet för den inbyggda komponentens Sling Model, som skapats i självstudiekursen Custom Component .
Förutsättningar prerequisites
Granska de verktyg och instruktioner som krävs för att konfigurera en lokal utvecklingsmiljö.
Om både Java™ 8 och Java™ 11 är installerade i systemet kan VS-kodens testkörare välja den lägre Java™-miljön när testerna körs, vilket resulterar i testfel. Om detta inträffar avinstallerar du Java™ 8.
Startprojekt
Ta en titt på den baslinjekod som självstudiekursen bygger på:
-
Kolla in grenen
tutorial/unit-testing-start
från GitHubcode language-shell $ cd aem-guides-wknd $ git checkout tutorial/unit-testing-start
-
Distribuera kodbasen till en lokal AEM med dina Maven-kunskaper:
code language-shell $ mvn clean install -PautoInstallSinglePackage
note note NOTE Om du använder AEM 6.5 eller 6.4 lägger du till profilen classic
till eventuella Maven-kommandon.code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
Du kan alltid visa den färdiga koden på GitHub eller checka ut koden lokalt genom att växla till grenen tutorial/unit-testing-start
.
Syfte
- Förstå grunderna för enhetstestning.
- Lär dig mer om ramverk och verktyg som ofta används för att testa AEM kod.
- Förstå alternativen för att gungera eller simulera AEM när du skriver enhetstester.
Bakgrund unit-testing-background
I den här självstudiekursen ska vi utforska hur du skriver enhetstester för vår Byline-komponents segmenteringsmodell (skapad i Skapa en anpassad AEM). Enhetstester är körtidstester skrivna i Java™ som verifierar förväntade beteenden hos Java™-kod. Varje enhetstest är vanligen litet och validerar resultatet av en metod (eller arbetsenheter) mot förväntade resultat.
Vi använder AEM bästa praxis och använder:
- JUnit 5
- Mockito Testing Framework
- wcm.io Test Framework (som bygger på Apache Sling Mocks)
Enhetstestning och Adobe Cloud Manager unit-testing-and-adobe-cloud-manager
Adobe Cloud Manager integrerar körning av enhetstest och rapportering av kodtäckning i sin CI/CD-pipeline för att uppmuntra och främja bästa praxis för enhetstestning AEM kod.
Även om kod för enhetstestning är en bra vana för alla kodbaser är det viktigt att kunna dra nytta av kodkvalitetstestningen och rapporteringsmöjligheterna genom att tillhandahålla enhetstester som Cloud Manager kan köra när man använder Cloud Manager.
Uppdatera testberoenden för Maven inspect-the-test-maven-dependencies
Det första steget är att undersöka Maven-beroenden för att stödja skrivandet och körningen av testerna. Det krävs fyra beroenden:
- JUnit5
- Mockito Test Framework
- Apache Sling Mocks
- AEM Mocks Test Framework (av io.wcm)
Testberoendena JUnit5, Mockito och AEM Mocks** läggs automatiskt till i projektet under installationen med AEM Maven-arkitypen.
-
Om du vill visa dessa beroenden öppnar du POM-filen för den överordnade reaktorn på aem-guides-wknd/pom.xml, går till
<dependencies>..</dependencies>
och visar beroendena för JUnit, Mockito, Apache Sling Mocks och AEM Mock Tests av io.wcm under<!-- Testing -->
. -
Kontrollera att
io.wcm.testing.aem-mock.junit5
är inställt på 4.1.0: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 Arketypen 35 genererar projektet med io.wcm.testing.aem-mock.junit5
version 4.1.8. Uppgradera till 4.1.0 om du vill följa resten av det här kapitlet. -
Öppna aem-guides-wknd/core/pom.xml och se att motsvarande testberoenden är tillgängliga.
En parallell källmapp i core -projektet innehåller enhetstesterna och eventuella stödtestfiler. Den här mappen test separerar testklasser från källkoden, men gör att testerna fungerar som om de finns i samma paket som källkoden.
Skapa JUnit-testet creating-the-junit-test
Enhetstester kan normalt mappa 1 till 1 med Java™-klasser. I det här kapitlet ska vi skriva ett JUnit-test för BylineImpl.java, som är den Sling-modell som stöder Byline-komponenten.
Plats där enhetstester lagras.
-
Skapa ett enhetstest för
BylineImpl.java
genom att skapa en ny Java™-klass undersrc/test/java
i en mappstruktur för Java™-paket som speglar platsen för den Java™-klass som ska testas.Eftersom vi testar
src/main/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImpl.java
skapa motsvarande enhetstest Java™-klass på
src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
Test
-suffixet i enhetstestfilenBylineImplTest.java
är en konvention som gör att vi kan- Identifiera den enkelt som testfil för
BylineImpl.java
- Men skiljer också testfilen från klassen som testas,
BylineImpl.java
Granska BylineImplTest.java reviewing-bylineimpltest-java
Nu är JUnit-testfilen en tom Java™-klass.
-
Uppdatera filen med följande kod:
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"); } }
-
Den första metoden
public void setUp() { .. }
kommenteras med JUnit:s@BeforeEach
, som instruerar JUnit-testköraren att köra den här metoden innan varje testmetod körs i den här klassen. Detta är en praktisk plats där du kan initiera vanliga testtillstånd som krävs för alla tester. -
De efterföljande metoderna är testmetoderna, vars namn är prefix med
test
enligt konvention och märkta med@Test
-anteckningen. Observera att som standard kommer alla våra tester att misslyckas eftersom vi ännu inte har implementerat dem.Till att börja med har vi en enda testmetod för varje offentlig metod för den klass vi testar, så här:
table 0-row-3 1-row-3 2-row-3 3-row-3 BylineImpl.java BylineImplTest.java getName() testas av testGetName() getOccupations() testas av testGetOccupations() isEmpty() testas av testIsEmpty() Dessa metoder kan vid behov färdigställas, vilket vi kommer att se senare i det här kapitlet.
När denna JUnit-testklass (kallas även JUnit-testfall) körs, kommer varje metod som är markerad med
@Test
att köras som ett test som antingen kan godkännas eller misslyckas.
core/src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
-
Kör JUnit Test Case genom att högerklicka på filen
BylineImplTest.java
och trycka på Run.
Som förväntat misslyckas alla tester eftersom de ännu inte har implementerats.Högerklicka på BylineImplTests.java > Kör
Granska BylineImpl.java reviewing-bylineimpl-java
När enhetstester skrivs finns det två primära metoder:
- TDD eller Test Driven Development, som innebär att enhetstesterna skrivs stegvis, omedelbart innan implementeringen utvecklas. Skriv ett test och gör testet.
- Utveckling av implementering först, vilket innebär att först utveckla arbetskoden och sedan skriva tester som validerar den koden.
I den här självstudiekursen används den senare metoden (eftersom vi redan har skapat en fungerande BylineImpl.java i ett tidigare kapitel). På grund av detta måste vi granska och förstå hur dess publika metoder fungerar, men också en del av dess implementeringsdetaljer. Detta kan låta tvärtom, eftersom ett bra test endast bör omfatta in- och utdata, men när AEM utförs måste olika implementeringsöverväganden göras för att man ska kunna konstruera arbetstester.
TDD krävs inom ramen för AEM och är bäst lämpat för AEM utvecklare som är skickliga på AEM utveckling och enhetstestning av AEM kod.
Konfigurera AEM testkontext setting-up-aem-test-context
De flesta koder som skrivits för AEM är beroende av JCR-, Sling- eller AEM-API:er, som i sin tur kräver att en AEM körs på rätt sätt.
Eftersom enhetstester utförs vid bygget, utanför en pågående AEM, finns det ingen sådan kontext. För att underlätta detta skapar wcm.ios AEM Mocks ett standardsammanhang som tillåter att dessa API:er fungerar till största delen som om de körs i AEM.
-
Skapa en AEM kontext med wcm.ios
AemContext
i BylineImplTest.java genom att lägga till det som ett JUnit-tillägg som dekorerats med@ExtendWith
i filen BylineImplTest.java . Tillägget hanterar alla initierings- och rensningsåtgärder som krävs. Skapa en klassvariabel förAemContext
som kan användas för alla testmetoder.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();
Den här variabeln,
ctx
, visar en AEM som innehåller vissa AEM- och Sling-abstraktioner:- BylineImpl Sling Model är registrerad i den här kontexten
- Mock JCR-innehållsstrukturer skapas i det här sammanhanget
- Anpassade OSGi-tjänster kan registreras i den här kontexten
- Innehåller olika vanliga nödvändiga modellobjekt och hjälpmedel, till exempel SlingHttpServletRequest-objekt, olika tjänster för modelldelning och AEM OSGi, till exempel ModelFactory, PageManager, Page, Template, ComponentManager, Component, TagManager, Tag, etc.
- Alla metoder för dessa objekt är inte implementerade!
- Och mycket mer!
Objektet
ctx
fungerar som startpunkt för större delen av vår modellkontext. -
I metoden
setUp(..)
, som körs före varje@Test
-metod, definierar du ett vanligt modelltestläge: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
registrerar den Sling-modell som ska testas i AEM-kontexten, så att den kan instansieras i@Test
-metoderna.load().json
läser in resursstrukturer i standardkontexten, vilket gör att koden kan interagera med dessa resurser som om de vore från en riktig databas. Resursdefinitionerna i filenBylineImplTest.json
läses in i JCR-standardkontexten under /content.BylineImplTest.json
finns inte än, så vi skapar den och definierar de JCR-resursstrukturer som behövs för testet.
-
JSON-filerna som representerar modellresursstrukturerna lagras under core/src/test/resources efter samma paketsökväg som JUnit Java™-testfilen.
Skapa en JSON-fil på
core/test/resources/com/adobe/aem/guides/wknd/core/models/impl
med namnet BylineImplTest.json med följande innehåll:code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline" } }
Denna JSON definierar en modellresurs (JCR-nod) för Byline-komponentenhetstestet. I det här skedet har JSON den minsta uppsättning egenskaper som krävs för att representera en innehållsresurs för en instickskomponent,
jcr:primaryType
ochsling:resourceType
.En allmän regel när du arbetar med enhetstester är att skapa den minimala uppsättningen av modellinnehåll, kontext och kod som krävs för att uppfylla varje test. Undvik frestelsen att bygga ut en komplett modellkontext innan du skriver testerna, eftersom det ofta leder till onödiga artefakter.
Nu när BylineImplTest.json finns, läses modellresursdefinitionerna in i kontexten vid sökvägen /content när
ctx.json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content")
körs.
Testar getName() testing-get-name
Nu när vi har skapat en grundläggande modellkontext kan vi skriva vårt första test för BylineImpls getName(). Det här testet måste säkerställa att metoden getName() returnerar det korrekta skrivna namnet som lagras i resursens name-egenskap.
-
Uppdatera metoden testGetName() i BylineImplTest.java enligt följande:
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
anger det förväntade värdet. Vi anger det här till Jane Done.ctx.currentResource
anger kontexten för den modellresurs som koden ska utvärderas mot, så detta anges som /content/byline eftersom det är där den ursprungliga modellens innehållsresurs läses in.Byline byline
instansierar Byline Sling-modellen genom att anpassa den från Mock Request-objektet.String actual
anropar den metod som vi testar,getName()
, i objektet Byline Sling Model.assertEquals
kontrollerar att det förväntade värdet matchar det värde som returneras av objektet Byline Sling Model. Om dessa värden inte är lika misslyckas testet.
-
Kör testet… och det misslyckas med en
NullPointerException
.Det här testet misslyckas INTE eftersom vi aldrig har definierat en
name
-egenskap i JSON-modellens, vilket kommer att göra att testet misslyckas, men testkörningen har inte kommit till den punkten! Det här testet misslyckas på grund av attNullPointerException
finns på själva benypobjektet. -
Om
@PostConstruct init()
genererar ett undantag iBylineImpl.java
förhindras Sling Model från att instansieras och detta Sling Model-objekt blir null.code language-java @PostConstruct private void init() { image = modelFactory.getModelFromWrappedRequest(request, request.getResource(), Image.class); }
Det visar sig att även om ModelFactory OSGi-tjänsten tillhandahålls via
AemContext
(via Apache Sling Context) så implementeras inte alla metoder, inklusivegetModelFromWrappedRequest(...)
som anropas i BylineImplsinit()
-metod. Detta resulterar i ett AbstractMethodError som i termen orsakar attinit()
misslyckas och den resulterande anpassningen avctx.request().adaptTo(Byline.class)
är ett null-objekt.Eftersom de angivna modellerna inte kan hantera koden måste vi implementera standardkontexten själva. För detta kan vi använda Mockito för att skapa ett ModelFactory-modellobjekt som returnerar ett modellbildobjekt när
getModelFromWrappedRequest(...)
anropas.Eftersom den här modelltypen måste finnas på plats för att instansiera Byline Sling Model kan vi lägga till den i metoden
@Before setUp()
. Vi måste också lägga tillMockitoExtension.class
i@ExtendWith
-anteckningen ovanför klassen BylineImplTest.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})
markerar klassen Test Case som ska köras med Mockito JUnit Jupiter Extension som tillåter användning av @Mock-anteckningar för att definiera modellobjekt på klassnivå.@Mock private Image
skapar ett modellobjekt av typencom.adobe.cq.wcm.core.components.models.Image
. Detta definieras på klassnivå så att@Test
-metoder kan ändra sitt beteende efter behov.@Mock private ModelFactory
skapar ett modellobjekt av typen ModelFactory. Det här är en helt sann Mockito-mock och har inga metoder implementerade på den. Detta definieras på klassnivå så att@Test
metoder kan ändra sitt beteende efter behov.when(modelFactory.getModelFromWrappedRequest(..)
registrerar modellbeteende för närgetModelFromWrappedRequest(..)
anropas i modellmodellobjektet ModelFactory. Resultatet som definieras ithenReturn (..)
är att returnera modellbildobjektet. Det här beteendet anropas bara när: den första parametern är lika medctx
s begäranobjekt, den andra parametern är ett Resource-objekt och den tredje parametern måste vara Core Components Image-klass. Vi accepterar alla resurser eftersom vi under testerna ställer inctx.currentResource(...)
på olika modellresurser som definieras i BylineImplTest.json. Observera att vi lägger till strängen leenient() eftersom vi senare vill åsidosätta det här beteendet för ModelFactory.ctx.registerService(..)
. registrerar Mock ModelFactory-objektet i AemContext, med den högsta rangordningen. Detta är obligatoriskt eftersom ModelFactory som används i BylineImpl:eninit()
injiceras via fältet@OSGiService ModelFactory model
. För att AemContext ska kunna injicera vårt-modellobjekt, som hanterar anrop tillgetModelFromWrappedRequest(..)
, måste vi registrera det som den högsta rangordningstjänsten av den typen (ModelFactory).
-
Kör testet igen och det misslyckas igen, men den här gången är det tydligt att meddelandet misslyckades.
testGetName() misslyckades på grund av försäkran
Vi får ett AssertionError som innebär att villkoret assert i testet misslyckades, och det anger att det förväntade värdet är "Jane Doe", men det faktiska värdet är null. Detta är rimligt eftersom egenskapen name inte har lagts till i resursdefinitionen mock /content/byline i BylineImplTest.json, så vi lägger till den:
-
Uppdatera BylineImplTest.json för att definiera
"name": "Jane Doe".
code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe" } }
-
Kör testet igen och
testGetName()
godkänns nu!
Testar getOccupations() testing-get-occupations
Okej bra! Det första testet har klarat! Låt oss gå vidare och testa getOccupations()
. Eftersom modellkontexten initierades i metoden @Before setUp()
är den tillgänglig för alla @Test
-metoder i det här testfallet, inklusive getOccupations()
.
Kom ihåg att den här metoden måste returnera en alfabetiskt sorterad lista med befattningar (fallande) som lagras i egenskapen ockupationer.
-
Uppdatera
testGetOccupations()
enligt följande: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
definierar det förväntade resultatet.ctx.currentResource
ställer in den aktuella resursen för att utvärdera kontexten mot standardresursdefinitionen på /content/byline. Detta garanterar att BylineImpl.java körs i kontexten för vår modellresurs.ctx.request().adaptTo(Byline.class)
instansierar Byline Sling-modellen genom att anpassa den från Mock Request-objektet.byline.getOccupations()
anropar den metod som vi testar,getOccupations()
, i objektet Byline Sling Model.assertEquals(expected, actual)
hävdar att den förväntade listan är densamma som den faktiska listan.
-
Kom ihåg, precis som
getName()
ovan, att BylineImplTest.json inte definierar yrken, så det här testet misslyckas om det körs eftersombyline.getOccupations()
returnerar en tom lista.Uppdatera BylineImplTest.json så att den innehåller en lista över yrken, och de är inställda i icke-alfabetisk ordning för att säkerställa att våra tester validerar att yrken sorteras alfabetiskt efter
getOccupations()
.code language-json { "byline": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wknd/components/content/byline", "name": "Jane Doe", "occupations": ["Photographer", "Blogger", "YouTuber"] } }
-
Kör testet, och återigen godkänns vi! Det ser ut som att få de sorterade arbetsuppgifterna att fungera!
testGetOccupations() passerar
Testing isEmpty() testing-is-empty
Den sista metoden för att testa isEmpty()
.
Testningen av isEmpty()
är intressant eftersom den kräver testning för olika villkor. Granska isEmpty()
-metoden för BylineImpl.java måste följande villkor testas:
- Returnera true när namnet är tomt
- Returnera true när yrken är null eller tomma
- Returnera true när bilden är null eller saknar src-URL
- Returnera falskt när namnet, befattningarna och bilden (med en src-URL) finns
För detta måste vi skapa testmetoder, där varje testning av ett specifikt villkor och nya modellresursstrukturer i BylineImplTest.json
för att köra dessa tester.
Den här kontrollen gjorde att vi kunde hoppa över testning för när getName()
, getOccupations()
och getImage()
är tomma eftersom det förväntade beteendet för det läget testas via isEmpty()
.
-
Det första testet testar villkoret för en helt ny komponent som inte har några egenskaper angivna.
Lägg till en ny resursdefinition i
BylineImplTest.json
och ge den det semantiska namnet emptycode 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": {...}
definierar en ny resursdefinition med namnet"empty" som bara har enjcr:primaryType
ochsling:resourceType
.Kom ihåg att vi läser in
BylineImplTest.json
ictx
innan varje testmetod körs i@setUp
, så den nya resursdefinitionen är omedelbart tillgänglig för oss i tester på /content/empty. -
Uppdatera
testIsEmpty()
enligt följande och ställ in den aktuella resursen på den nya empty-modellresursdefinitionen.code language-java @Test public void testIsEmpty() { ctx.currentResource("/content/empty"); Byline byline = ctx.request().adaptTo(Byline.class); assertTrue(byline.isEmpty()); }
Kör testet och se till att det lyckas.
-
Skapa sedan en uppsättning metoder för att se till att
isEmpty()
returnerar true om någon av de obligatoriska datapunkterna (namn, befattningar eller bild) är tom.För varje test används en diskret modellresursdefinition. Uppdatera BylineImplTest.json med ytterligare resursdefinitioner för without-name och without-ockations.
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" } }
Skapa följande testmetoder för att testa alla dessa lägen.
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()
testar mot den tomma modellresursdefinitionen och försäkrar attisEmpty()
är sant.testIsEmpty_WithoutName()
testar mot en standardresursdefinition som har befattningar men inget namn.testIsEmpty_WithoutOccupations()
testar mot en standardresursdefinition som har ett namn men inga arbeten.testIsEmpty_WithoutImage()
testar mot en modellresursdefinition med ett namn och en funktion, men ställer in att standardbilden ska returneras till null. Observera att vi vill åsidosätta beteendetmodelFactory.getModelFromWrappedRequest(..)
som definierats isetUp()
för att se till att det bildobjekt som returneras av anropet är null. Mockito-stubs-funktionen är strikt och vill inte ha duplicerad kod. Därför ställer vi in parametern medlenient
-inställningar för att explicit notera att vi åsidosätter beteendet i metodensetUp()
.testIsEmpty_WithoutImageSrc()
testar mot en modellresursdefinition med ett namn och en funktion, men ställer in att modellbilden ska returnera en tom sträng närgetSrc()
anropas. -
Skriv slutligen ett test för att se till att isEmpty() returnerar false när komponenten är korrekt konfigurerad. För det här villkoret kan vi återanvända /content/byline som representerar en fullt konfigurerad Byline-komponent.
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()); }
-
Kör nu alla enhetstester i filen BylineImplTest.java och granska Java™ Test Report.
Kör enhetstester som en del av bygget running-unit-tests-as-part-of-the-build
Enhetstester utförs och krävs för att passera som en del av maven-byggnaden. Detta garanterar att alla tester lyckas innan ett program distribueras. För att köra Maven-mål som paketering eller installation anropas automatiskt och alla enhetstester i projektet måste godkännas.
$ mvn package
$ mvn package
Om vi ändrar en testmetod till att misslyckas, misslyckas också bygget och rapporterar att testet misslyckades och varför.
Granska koden review-the-code
Visa den färdiga koden på GitHub eller granska och distribuera koden lokalt på Git-grenen tutorial/unit-testing-solution
.