mocking private static
Lär dig att håna privata, statiska och ogiltiga metoder i Mockito med exempel:
I denna serie hands-on Självstudier om Mockito , vi tittade på olika typer av Mockito Matchers i den senaste handledningen.
Generellt sett hånar privata och statiska metoder under kategorin ovanlig hån.
Om behovet uppstår för att håna privata och statiska metoder / klasser, indikerar det dåligt omformad kod och är inte riktigt en testbar kod och är troligtvis en del äldre kod som inte användes för att vara mycket enhetstestvänlig.
Med detta sagt finns det fortfarande stöd för Mocking privata och statiska metoder av få enhetstestramar som PowerMockito (och inte direkt av Mockito).
Spottande 'ogiltiga' metoder är vanliga eftersom det kan finnas metoder som i princip inte returnerar någonting, som att uppdatera en databaserad (betrakta det som en PUT-operation för en Rest API-slutpunkt som accepterar en ingång och inte returnerar någon utdata).
Mockito ger fullt stöd för hånfulla ogiltiga metoder, vilket vi kommer att se med exempel i den här artikeln.
bästa spionapp för Android
Vad du kommer att lära dig:
- Powermock - En kort introduktion
- Hånfulla privata metoder
- Hånfulla statiska metoder
- Spottande ogiltiga metoder
- tips och tricks
- Slutsats
- Rekommenderad läsning
Powermock - En kort introduktion
För Mockito finns det inget direkt stöd för att håna privata och statiska metoder. För att testa privata metoder måste du refaktorera koden för att ändra åtkomst till skyddad (eller paket) och du måste undvika statiska / slutliga metoder.
Mockito, enligt min mening ger inte avsiktligt stöd för dessa typer av mocks, eftersom användning av dessa typer av kodkonstruktioner är kodluktar och dåligt utformad kod.
Men det finns ramar som stöder hån för privata och statiska metoder.
Powermock utökar kapaciteten i andra ramverk som EasyMock och Mockito och ger möjlighet att håna statiska och privata metoder.
# 1) Hur: Powermock gör detta med hjälp av anpassad bytecode-manipulation för att stödja håna privata och statiska metoder, slutklasser, konstruktörer och så vidare.
# 2) Paket som stöds: Powermock tillhandahåller två förlängnings-API: er - en för Mockito och en för easyMock. För denna artikel kommer vi att skriva exempel med Mockito-förlängningen för power mock.
# 3) Syntax :Powermockito har en nästan liknande syntax som Mockito, förutom några ytterligare metoder för att håna statiska och privata metoder.
# 4) Installation av Powermockito
För att inkludera Mockito-biblioteket i gradbaserade projekt, nedan är biblioteken som ska inkluderas:
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4' testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
Liknande beroenden finns också för maven.
Powermock-api-mockito2 - Biblioteket måste innehålla Mockito-tillägg för Powermockito.
Powermock-modul-junit4 - Modulen krävs för att inkludera PowerMockRunner (som är en anpassad löpare som ska användas för att köra tester med PowerMockito).
En viktig punkt att notera här är att PowerMock inte stöder Junit5 testlöpare. Därför måste testerna skrivas mot Junit4 och testerna måste utföras med PowerMockRunner.
För att använda PowerMockRunner - testklassen måste antecknas med @RunWith (PowerMockRunner.class)
Låt oss nu diskutera, håna privata, statiska och ogiltiga metoder i detalj!
Hånfulla privata metoder
Att håna privata metoder, som kallas internt från en metod som testas, kan vara oundviklig vid vissa tider. Med hjälp av powermockito är detta möjligt och verifieringen görs med en ny metod som heter 'verifiera privat'
Låt oss ta enExempel där metoden under test kallar en privat metod (som returnerar en boolean). För att stubba den här metoden för att returnera true / false beroende på testet måste en stub ställas in på den här klassen.
För det här exemplet skapas klassen som testas som en spioninstans med spott på några gränssnittsanrop och privata metodanrop.
Viktiga punkter för Mock Private Method:
# 1) Testmetoden eller testklassen måste antecknas med @ PrepareForTest (ClassUnderTest). Denna kommentar ber powerMockito att förbereda vissa klasser för testning.
Det här är mest de klasser som behöver vara Bytecode manipulerad . Vanligtvis för slutklasser, klasser som innehåller privata och / eller statiska metoder som måste hånas under testningen.
Exempel:
@PrepareForTest(PriceCalculator.class)
#två) För att ställa in stub på en privat metod.
Syntax - när (mock eller spion instans, 'privateMethodName'). thenReturn (// returvärde)
Exempel:
when (priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false);
# 3) För att verifiera den stubbade privata metoden.
Syntax - verifiera privat (mockedInstance) .invoke (“privateMethodName”)
Exempel:
verifyPrivate (priceCalculator).invoke('isCustomerAnonymous');
Komplett testprov: Fortsätter samma exempel från tidigare artiklar, där priceCalculator har några hånade beroenden som itemService, userService etc.
Vi har skapat en ny metod som kallas - beräknaPriceWithPrivateMethod, som anropar en privat metod inom samma klass och returnerar om kunden är anonym eller inte.
@Test @PrepareForTest(PriceCalculator.class) public void calculatePriceForAnonymous_witStubbedPrivateMethod_returnsCorrectPrice() throws Exception { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); double expectedPrice = 90.00; // Setting up stubbed responses using mocks when(priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false); when(mockedItemService.getItemDetails(123)).thenReturn(item1); // Act double actualDiscountedPrice = priceCalculatorSpy.calculatePriceWithPrivateMethod(123); // Assert verifyPrivate(priceCalculator).invoke('isCustomerAnonymous'); assertEquals(expectedPrice, actualDiscountedPrice); }
Hånfulla statiska metoder
Statiska metoder kan hånas på ett liknande sätt som vi såg för privata metoder.
När en metod som testas innebär att man använder en statisk metod från samma klass (eller från en annan klass), måste vi inkludera den klassen i PreparForTest-anteckningen före testet (eller i testklassen).
Viktiga punkter för Mock Static Methods:
# 1) Testmetoden eller testklassen måste antecknas med @ PrepareForTest (ClassUnderTest). I likhet med att håna privata metoder / klasser krävs det också för statiska klasser.
#två) Ett extra steg som krävs för statiska metoder är - mockStatic (// namn på statisk klass)
Exempel:
mockStatic(DiscountCategoryFinder.class)
# 3) Att ställa in stub på en statisk metod är lika bra som att stubba vilken metod som helst på alla andra gränssnitt / klassmodeller.
Till exempel: För att stubba getDiscountCategory () (som returnerar en enum DiscountCategory med värden PREMIUM & ALLMÄNT) statisk metod i DiscountCategoryFinder-klassen, helt enkelt stubba enligt följande:
when (DiscountCategoryFinder. getDiscountCategory ()).thenReturn(DiscountCategory. PREMIUM );
# 4) För att verifiera mock-installationen på den slutliga / statiska metoden kan metoden verifiera statisk () användas.
Exempel:
verifyStatic (DiscountCategoryFinder.class, times (1));
Spottande ogiltiga metoder
Låt oss först försöka förstå vilken typ av användningsfall som kan innebära stubbande ogiltiga metoder:
# 1) Metodsamtal till exempel - som skickar ett e-postmeddelande under processen.
Till exempel :Antag att du ändrar ditt lösenord för ditt internetbank-konto, när ändringen lyckas får du ett meddelande via din e-post.
Detta kan betraktas som / changePassword som ett POST-samtal till Bank API som inkluderar ett ogiltigt metodanrop för att skicka ett e-postmeddelande till kunden.
#två) Ett annat vanligt exempel på det ogiltiga metodanropet är uppdaterade förfrågningar till en DB som tar lite input och returnerar ingenting.
Stubbande ogiltiga metoder (dvs de metoder som inte returnerar någonting eller annars ger ett undantag) kan hanteras med funktionerna doNothing (), doThrow () och doAnswer (), doCallRealMethod () . Det kräver att stubben ställs in med ovanstående metoder enligt testförväntningarna.
Observera också att alla ogiltiga metodsamtal är som standard hånade till doNothing (). Därför, även om en explicit mock-installation inte görs på TOMHET metodsamtal är standardbeteendet fortfarande att göra ingenting ().
Låt oss se exempel på alla dessa funktioner:
För alla exempel, låt oss anta att det finns en klass StudentScoreUpdates som har en metod beräknaSumAndStore (). Denna metod beräknar summan av poäng (som inmatning) och kallar a tomhet metod updateScores () på databaseImplementation-instans.
public class StudentScoreUpdates { public IDatabase databaseImpl; public StudentScoreUpdates(IDatabase databaseImpl) { this.databaseImpl = databaseImpl; } public void calculateSumAndStore(String studentId, int() scores) { int total = 0; for(int score : scores) { total = total + score; } // write total to DB databaseImpl.updateScores(studentId, total); } }
Vi kommer att skriva enhetstest för mock-metodanropet med nedanstående exempel:
# 1) doNothing () - doNothing () är standardbeteendet för annulleringsmetodsamtal i Mockito, det vill säga även om du verifierar ett samtal om ogiltig metod (utan att uttryckligen ställa in ett tomrum till doNothing (), kommer verifieringen fortfarande att lyckas)
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(anyString(), anyInt()); }
Andra användningsområden tillsammans med doNothing ()
till) När annulleringsmetoden anropas flera gånger och du vill ställa in olika svar för olika anrop, som - doNothing () för den första anropet och kasta ett undantag för nästa anrop.
Till exempel :Ställ in mock så här:
Mockito. doNothing ().doThrow(new RuntimeException()).when(mockDatabase).updateScores( anyString (), anyInt ());
b) När du vill fånga de argument som tomrummetoden anropades med, bör ArgumentCaptor-funktionaliteten i Mockito användas. Detta ger en extra verifiering av argument som metoden anropades med.
Exempel med ArgumentCaptor:
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); ArgumentCaptor studentIdArgument = ArgumentCaptor.forClass(String.class); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(studentIdArgument.capture(), anyInt()); assertEquals('Student1', studentIdArgument.getValue()); }
# 2) doTrow ()- Detta är användbart när du helt enkelt vill göra ett undantag när ogiltighetsmetoden åberopas från metoden som testas.
bästa övervakningsprogram för CPU och GPU
Till exempel:
Mockito.doThrow(newRuntimeException()).when(mockDatabase).updateScores ( anyString (), anyInt ());
# 3) doAnswer ()- doAnswer () ger helt enkelt ett gränssnitt för att göra anpassad logik.
T.ex. Ändra något värde genom de skickade argumenten, returnera anpassade värden / data som en normal stub inte kunde ha returnerat särskilt för ogiltiga metoder.
I syfte att demonstrera - jag har stoppat metoden updateScores () void för att returnera en ' svar() ”Och skriv ut värdet på ett av argumenten som borde ha skickats när metoden borde ha anropats.
Kodexempel:
@Test public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabaseImpl); int() scores = {60,70,90}; Mockito.doCallRealMethod().when(mockDatabaseImpl).updateScores(anyString(), anyInt()); doAnswer(invocation -> { Object() args = invocation.getArguments(); Object mock = invocation.getMock(); System.out.println(args(0)); return mock; }).when(mockDatabaseImpl).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabaseImpl, Mockito.times(1)).updateScores(anyString(), anyInt()); }
# 4) doCallRealMethod ()- Partiella mocks liknar stubbar (där du kan ringa riktiga metoder för några av metoderna och stubba ut resten).
För ogiltiga metoder ger mockito en speciell funktion som kallas doCallRealMethod () som kan användas när du försöker ställa in mocken. Vad detta kommer att göra är att kalla den verkliga ogiltiga metoden med de faktiska argumenten.
Till exempel:
Mockito. doCallRealMethod ().when(mockDatabaseImpl).updateScores( anyString (), anyInt ());
tips och tricks
# 1) Inkluderar flera statiska klasser i samma testmetod / klass- Använda PowerMockito om det finns ett behov av att håna flera Static of Final-klasser så klassnamnen i @ PrepareForTest annotering kan nämnas som kommaseparerat värde som en matris (den accepterar i princip en matris av klassnamnen).
Exempel:
@PrepareForTest({PriceCalculator.class, DiscountCategoryFinder.class})
Som visas i exemplet ovan antar att både PriceCalculator och DiscountCategoryFinder är slutklasser som måste hånas. Båda dessa kan nämnas som en rad klasser i PrepareForTest-anteckningen och kan stubbas i testmetoden.
# 2) PrepareForTest-attributpositionering - Positioneringen av detta attribut är viktigt med avseende på vilken typ av test som ingår i testklassen.
Om alla tester behöver använda samma slutklass, är det vettigt att nämna detta attribut på testklassnivå vilket helt enkelt innebär att den förberedda klassen kommer att vara tillgänglig för alla testmetoder. Till skillnad från detta, om anteckningen nämns i testmetoden, kommer den endast att vara tillgänglig för just de specifika testerna
Slutsats
I denna handledning diskuterade vi olika tillvägagångssätt för att håna statiska, slutliga och ogiltiga metoder.
Även om man använder många statiska eller slutliga metoder hindrar testbarhet, och ändå finns det stöd tillgängligt för testning / hån för att hjälpa till att skapa enhetstester för att uppnå större förtroende för koden / applikationen även för äldre kod som vanligtvis inte är van vid utformas för testbarhet.
För statiska och slutliga metoder har Mockito inte ett out of box-stöd, men bibliotek som PowerMockito (som ärver mycket av Mockito) ger sådant stöd och måste faktiskt utföra bytkodshantering för att stödja dessa funktioner.
Mockito out of the box stöder stubbande ogiltiga metoder och tillhandahåller olika metoder som doNothing, doAnswer, doThrow, doCallRealMethod etc. och kan användas enligt testets krav.
De vanligaste Mockito-intervjufrågorna beskrivs i vår nästa handledning.
PREV-handledning | NÄSTA självstudie
Rekommenderad läsning
- Mockito Tutorial: Mockito Framework for Mocking in Unit Testing
- Topp 12 Mockito-intervjufrågor (Mocking Framework Interview)
- Statisk i C ++
- Java-trådar med metoder och livscykel
- Skapa Mocks and Spies i Mockito med kodexempel
- Olika typer av matchare från Mockito
- Metoder och tekniker för förebyggande av defekter
- Hur man använder metoder i SoapUI för bulktestutförande - SoapUI-handledning # 10