different types matchers provided mockito
sletning af et element fra en array-java
En introduktion til forskellige typer matchere i Mockito.
Mocks and Spies i Mockito blev forklaret detaljeret i vores tidligere tutorial af detaljeret Mockito træningsserie .
Hvad er Matchers?
Matchere er som regex eller jokertegn, hvor du i stedet for en bestemt input (og eller output) angiver et interval / type input / output baseret på hvilke stubs / spioner, der kan hvile, og opkald til stubs kan verificeres.
Alle Mockito matchere er en del af ' Mockito ' statisk klasse.
Matchers er et kraftfuldt værktøj, der muliggør en kortfattet måde at oprette stubber på samt at verificere påkald på stubbene ved at nævne argumentinput som generiske typer til specifikke værdier afhængigt af brugssagen eller scenariet.
Hvad du lærer:
Typer af matchere i Mockito
Der er stort set to typer matchere i Mockito eller med hensyn til brug kan matchere bruges til nedenstående 2 kategorier:
- Argument Matchers under opsætning af stub
- Verifikationsmatchere til verificering af faktiske opkald til stubber
For begge typer matchere, dvs. argument og verifikation, leverer Mockito et stort sæt matchere (klik her for at få en komplet liste over matcherne).
Argument Matchers
Nedenfor er de mest anvendte:
For alt det nedenstående, lad os overveje at teste en IntegerList:
final List mockedIntList = mock(ArrayList.class);
# 1) any () - Accepterer ethvert objekt (inklusive null).
when (mockedIntList.get( any ())).thenReturn(3);
#to) enhver (java sprogklasse) -
Eksempel : any (ClassUnderTest.class) - Dette er en mere specifik variant af enhver () og accepterer kun objekter af klassetypen, der er nævnt som skabelonparameteren.
when (mockedIntList.get( any (Integer.class))).thenReturn(3);
# 3) anyBoolean (), anyByte (), anyInt (), anyString (), anyDouble (), anyFloat (), anyList () og mange flere - Alle disse accepterer ethvert objekt af den tilsvarende datatype samt null-værdier.
when (mockedIntList.get( any Int())).thenReturn(3);
# 4) Specifikke argumenter - I tilfælde, hvor faktiske argumenter er kendt på forhånd, anbefales det altid at bruge dem, da de giver mere tillid i forhold til generiske argumenttyper.
Eksempel:
when(mockedIntList.get(1)).thenReturn(3);
Verifikationsmatchere
Der er nogle specialiserede matchere, der er tilgængelige for at forvente / hævde ting som nej. af påkald på mock.
For alle nedenstående matchere skal vi overveje den samme liste med eksempler, som vi har brugt før.
final List mockedIntList = mock(ArrayList.class);
# 1) Mock Invocations
(jeg) Enkel påkaldelse på Mock verificerer, om den spottede metode blev kaldt / interageret eller ikke ved at indstille størrelsen på den spottede liste til 5.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList).size();
(ii) Specifikt antal interaktioner med en hånet metode bekræfter antallet af nr. af gange forventede man at blive kaldt.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList, times(1)).size();
For at verificere for 0 interaktioner skal du blot ændre værdien fra 1 til 0 som argument for times () matcher.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList, times(0)).size();
I tilfælde af fejl returnerer det følgende undtagelser:
til) Når de forventede påkaldelser er mindre end de faktiske påkaldelser:
Eksempel: Ønskes 2 gange, men påberåbes 3 gange, så vender Mockito tilbage - “ verification.TooManyActualInvocations '
hvordan man åbner en jar-fil med java på Windows 10
Eksempel kode:
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(3); response = mockedIntList.get(100); // Assert verify(mockedIntList, times(2)).get(anyInt());
b) Når de forventede påkaldelser er mere end de faktiske påkaldelser:
Eksempel: Ønskes 2 gange, men påberåbes 1 gang, så vender Mockito tilbage - “ verification.TooLittleActualInvocations '
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(3); response = mockedIntList.get(100); // Assert verify(mockedIntList, times(4)).get(anyInt());
(iii) Ingen interaktioner med den specifikke metode til det spottede objekt.
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); // Assert verify(mockedIntList, never()).size();
(iv) Bekræft rækkefølgen af spottede interaktioner - Dette er især nyttigt, når du vil sikre den rækkefølge, som metoderne på de spottede objekter blev kaldt til.
Eksempel: Database-lignende operationer, hvor en test skal kontrollere rækkefølgen, i hvilken databaseopdateringerne skete.
For at illustrere dette ved eksempel - Lad os fortsætte med den samme liste som eksempler.
Lad os nu antage, at rækkefølgen af opkald til listen over metoder var i rækkefølge, dvs. få (5), størrelse (), få (2). Så rækkefølgen af verifikation skal også være den samme.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); when(mockedIntList.size()).thenReturn(100); InOrder mockInvocationSequence = Mockito.inOrder(mockedIntList); // Act int response = mockedIntList.get(5); int size = mockedIntList.size(); response = mockedIntList.get(2); // Assert mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList).size(); mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt());
I tilfælde af forkert verifikationssekvens kastes en undtagelse af Mockito - dvs. “ verification.VerificationInOrderFailure ”.
Så i ovenstående eksempel, hvis jeg ændrer rækkefølgen for verifikation ved at udveksle de sidste 2 linjer, begynder jeg at få undtagelsen VerificationInOrderFailure.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); when(mockedIntList.size()).thenReturn(100); InOrder mockInvocationSequence = Mockito.inOrder(mockedIntList); // Act int response = mockedIntList.get(5); int size = mockedIntList.size(); response = mockedIntList.get(2); // Assert mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList).size();
(v) Bekræft, at interaktion har fundet sted mindst / mindst antal gange.
(til) i det mindste:
Eksempel: mindst (3) - Kontrollerer, at den spottede genstand blev påkaldt / interageret med mindst tre gange under testen. Så enhver af interaktionerne 3 eller større end 3 skal gøre verifikationen vellykket.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(2); // Assert verify(mockedIntList, atLeast(2)).get(anyInt());
I tilfælde af fejl, dvs. når de faktiske påkaldelser ikke stemmer overens, kastes den samme undtagelse som med matcheren times (), dvs. verification.TooLittleActualInvocations ”
(b) højst:
Eksempel: højst (3) - verificerer, om det spottede objekt blev påkaldt / interageret med mindst tre gange under testen. Så enhver af 0,1,2 eller 3 interaktioner med mocken skal gøre verifikationen vellykket.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(2); // Assert verify(mockedIntList, atMost(2)).get(anyInt()); verify(mockedIntList, atMost(2)).size();
# 2) Argument Matching
I ovenstående påkaldelse kan matchere kombineres sammen med argumentmatcherne for at validere de argumenter, som mock blev kaldt til.
- nogen()
- Specifikke værdier - Bekræft med de specifikke værdier, når argumenterne er kendt på forhånd.
- Andre argumentmatchere som - anyInt (), anyString () osv.
Tips & tricks
# 1) Brug af Argument Capture under verifikation
Bekræftelse af argumentfangst er typisk nyttigt, når argumentet, der bruges af en stubbed-metode, ikke sendes direkte via et metodekald, men oprettes internt, når metoden under test kaldes.
Dette er i det væsentlige nyttigt, hvor din metode afhænger af en eller flere samarbejdspartnere, hvis adfærd er blevet stubbet. Argumenterne, der sendes til disse samarbejdspartnere, er et internt objekt eller et helt nyt argument.
Validering af det faktiske argument, som samarbejdspartnerne ville være blevet kaldt med, sikrer stor tillid til den kode, der testes.
Mockito leverer ArgumentCaptor, som kan bruges med verifikation, og når 'AgumentCaptor.getValue ()' kaldes, kan vi hævde det faktiske fangede argument mod den forventede.
hvordan man kører en .swf
For at illustrere dette henvises til eksemplet nedenfor:
I nedenstående metode er calcPrice modellen med klassen InventoryModel oprettet inde i metodekroppen, som derefter bruges af InventoryService til opdatering.
Hvis du nu vil skrive en test for at validere, hvilket argument inventarServicen kaldes til, kan du blot bruge ArgumentCaptor-objektet af typen InventoryModel-klasse.
Metode under test:
public double calculatePrice(int itemSkuCode) { double price = 0; // get Item details ItemSku sku = itemService.getItemDetails(itemSkuCode); // update item inventory InventoryModel model = new InventoryModel(); model.setItemSku(sku); model.setItemSuppliers(new String(){'Supplier1'}); inventoryService.updateInventory(model, 1); return sku.getPrice(); }
Testkode: Se på verificeringstrinnet, hvor inventarService er verificeret, argumentCaptor-objektet erstattes af hvilket argument, der skal matches.
Påstå derefter værdien ved at påberåbe sig getValue () -metoden på ArgumentCaptor-objektet.
Eksempel: ArgumentCaptorObject.getValue ()
public void calculatePrice_withValidItemSku_returnsSuccess() { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); CustomerProfile customerProfile = new CustomerProfile(); customerProfile.setExtraLoyaltyDiscountPercentage(2.00); double expectedPrice = 93.00; // Arrange when(mockedItemService.getItemDetails(anyInt())).thenReturn(item1); ArgumentCaptor argCaptorInventoryModel = ArgumentCaptor.forClass(InventoryModel.class); // Act priceCalculator.calculatePrice(1234); // Assert verify(mockedItemService).getItemDetails(anyInt()); verify(mockedInventoryService).updateInventory(argCaptorInventoryModel.capture(), eq(1)); assertEquals(argCaptorInventoryModel.getValue().itemSku, item1);
Uden ArgumentCaptor ville der ikke være nogen måde at identificere hvilket argument tjenestekaldet blev foretaget med. Bedst muligt er at bruge 'enhver ()' eller 'enhver (InventoryModel.class)' til at verificere argumenter.
# 2) Almindelige undtagelser / fejl, når du bruger Matchers
Mens du bruger Matchers, er der visse konventioner, der skal følges, som hvis de ikke følges, resulterer i, at en undtagelse kastes. Den mest almindelige, som jeg stødte på, er under stubning og verificering.
Hvis du bruger argumentMatchers, og hvis den stubbed-metode har mere end et argument (er), skal enten alle argumenterne nævnes med matchere, ellers skal ingen af dem have matchere. Hvad betyder det nu?
Lad os prøve at forstå dette med et scenario (og derefter kodeeksempel til dette scenario)
- Antag, at metoden under test har en signatur som -
concatenateString (String arg1, String arg2) - Nu når du stubber - antag at du kender værdien af arg1, men arg2 er ukendt, så du beslutter dig for at bruge en argumentmatcher som - any () eller anyString () og angive en værdi for det første argument som en tekst 'hej'.
- Når ovenstående trin er implementeret, og testen udføres, kaster testen en undtagelse kaldet 'InvalidUseOfMatchersException'
Lad os prøve at forstå dette med et eksempel:
Testkode:
// Arrange when(a gMatcher.concatenateString('hello', anyString())).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'abc'); // Assert verify(argMatcher).concatenateString(anyString(), anyString());
Klasse under test:
public class ArgMatcher { public String concatenateString(String arg1, String arg2) { return arg1.concat(arg2); } }
Når ovenstående test udføres, vender den tilbage i “ InvalidUseOfMatchersException '
Hvad er årsagen til denne undtagelse nu?
Det er stubbingen ved hjælp af del matchere og del fast streng, dvs. vi har nævnt en argument matcher som 'hej' og anden som anyString (). Nu er der 2 måder at slippe af med denne slags undtagelser (bemærk også - at denne adfærd gælder for både Mock-opsætninger såvel som adfærd).
# 1) Brug Argument Matchers til alle argumenterne:
// Arrange when(a gMatcher.concatenateString(anyString(), anyString())).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'abc'); // Assert verify(argMatcher).concatenateString(anyString(), anyString());
# 2) Brug eq () som Argument Matcher, hvor argumentet er kendt. Så i stedet for at angive argumentet som “hej”, skal du angive det som “eq (“ hej ”), og dette skal gøre stubbingen vellykket.
// Arrange when(argMatcher.concatenateString(anyString(), eq('world'))).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'world'); // Assert verify(argMatcher).concatenateString(anyString(), eq('world'));
Konklusion
I denne artikel så vi, hvordan man bruger forskellige typer matchere leveret af Mockito.
Her dækkede vi de mest anvendte. For at henvise til den komplette liste er Mockito Library-dokumentation en god kilde til reference.
Se vores kommende vejledning for at vide mere om private, statiske og ugyldige metoder til mocking.
PREV-vejledning | NÆSTE vejledning
Anbefalet læsning
- Oprettelse af Mocks and Spies i Mockito med kodeeksempler
- Mockito Tutorial: Mockito Framework for Mocking in Unit Testing
- Typer af risici i softwareprojekter
- Python-datatyper
- C ++ datatyper
- Top 12 Mockito Interview Spørgsmål (Mocking Framework Interview)
- Mocking private, statiske og ugyldige metoder ved hjælp af Mockito
- Typer af arv i C ++