Een gids voor JMockit-verwachtingen

1. Inleiding

Dit artikel is het tweede deel in de JMockit-serie. Misschien wilt u het eerste artikel lezen, omdat we ervan uitgaan dat u al bekend bent met de basisprincipes van JMockit.

Vandaag gaan we dieper in op de verwachtingen. We zullen laten zien hoe u meer specifieke of generieke argumentafstemming kunt definiëren en hoe u meer geavanceerde manieren kunt definiëren om waarden te definiëren.

2. Overeenkomstige argumentwaarden

De volgende benaderingen zijn van toepassing op beide Verwachtingen net zoals Verificaties.

2.1. "Alle" velden

JMockit biedt een set hulpprogramma-velden om het matchen van argumenten algemener te maken. Een van deze hulpprogramma's is de anyX velden.

Deze zullen controleren of een waarde is doorgegeven en er is er een voor elk primitief type (en de bijbehorende wrapper-klasse), een voor strings en een 'universeel' type van het type Voorwerp.

Laten we een voorbeeld bekijken:

openbare interface ExpectationsCollaborator {String methodForAny1 (String s, int i, Boolean b); void methodForAny2 (Long l, List lst); } @Test openbare ongeldige test (@Mocked ExpectationsCollaborator mock) gooit uitzondering {nieuwe verwachtingen () {{mock.methodForAny1 (anyString, anyInt, anyBoolean); result = "any"; }}; Assert.assertEquals ("any", mock.methodForAny1 ("barfooxyz", 0, Boolean.FALSE)); mock.methodForAny2 (2L, nieuwe ArrayList ()); nieuwe FullVerifications () {{mock.methodForAny2 (anyLong, (List) any); }}; }

U moet er rekening mee houden bij het gebruik van de ieder veld, je moet het casten naar het verwachte type. De volledige lijst met velden is aanwezig in de documentatie.

2.2. "Met" methoden

JMockit biedt ook verschillende methoden om te helpen bij het matchen van generieke argumenten. Dat zijn de met X methoden.

Deze zorgen voor een iets geavanceerdere matching dan de anyX velden. We kunnen hier een voorbeeld zien waarin we een verwachting zullen definiëren voor een methode die wordt geactiveerd met een string die foo, een geheel getal dat niet gelijk is aan 1, een niet-nul Boolean en elk exemplaar van de Lijst klasse:

openbare interface ExpectationsCollaborator {String methodForWith1 (String s, int i); void methodForWith2 (Boolean b, List l); } @Test public void testForWith (@Mocked ExpectationsCollaborator mock) gooit uitzondering {nieuwe verwachtingen () {{mock.methodForWith1 (withSubstring ("foo"), withNotEqual (1)); result = "met"; }}; assertEquals ("with", mock.methodForWith1 ("barfooxyz", 2)); mock.methodForWith2 (Boolean.TRUE, nieuwe ArrayList ()); nieuwe Verificaties () {{mock.methodForWith2 (withNotNull (), withInstanceOf (List.class)); }}; }

U kunt de volledige lijst met met X methoden op de documentatie van JMockit.

Houd er rekening mee dat het bijzondere met (gemachtigde) en withArgThat (Matcher) zullen in hun eigen onderafdeling worden behandeld.

2.3. Null is niet null

Iets dat goed is om eerder dan later te begrijpen, is dat nul wordt niet gebruikt om een ​​argument te definiëren waarvoor nul is overgegaan in een mock.

Werkelijk, nul wordt gebruikt als syntactische suiker om te definiëren dat elk object zal worden doorgegeven (dus het kan alleen worden gebruikt voor parameters van het referentietype). Om specifiek te verifiëren dat een bepaalde parameter de nul referentie, de withNull () matcher kan worden gebruikt.

Voor het volgende voorbeeld zullen we het gedrag van een mock definiëren, dat moet worden geactiveerd wanneer de doorgegeven argumenten zijn: elke string, elke lijst en een nul referentie:

openbare interface ExpectationsCollaborator {String methodForNulls1 (String s, List l); void methodForNulls2 (String s, List l); } @Test openbare ongeldige testWithNulls (@Mocked ExpectationsCollaborator mock) {new Expectations () {{mock.methodForNulls1 (anyString, null); result = "null"; }}; assertEquals ("null", mock.methodForNulls1 ("blablabla", nieuwe ArrayList ())); mock.methodForNulls2 ("blablabla", null); nieuwe Verificaties () {{mock.methodForNulls2 (anyString, (List) withNull ()); }}; }

Let op het verschil: nul betekent elke lijst en withNull () betekent een nul verwijzing naar een lijst. Dit voorkomt in het bijzonder de noodzaak om de waarde naar het gedeclareerde parametertype te casten (zie dat het derde argument moest worden gegoten, maar niet het tweede).

De enige voorwaarde om dit te kunnen gebruiken is dat er ten minste één expliciete argument matcher is gebruikt voor de verwachting (ofwel een met methode of een ieder veld).

2.4. Veld "Times"

Soms willen we beperkenhet aantal aanroepen verwacht voor een bespotte methode. Hiervoor heeft JMockit de gereserveerde woorden keer, minTimes en maxTimes (alle drie staan ​​alleen niet-negatieve gehele getallen toe).

openbare interface ExpectationsCollaborator {void methodForTimes1 (); ongeldige methodForTimes2 (); ongeldige methodForTimes3 (); } @Test openbare ongeldige testWithTimes (@Mocked ExpectationsCollaborator mock) {new Expectations () {{mock.methodForTimes1 (); tijden = 2; mock.methodForTimes2 (); }}; mock.methodForTimes1 (); mock.methodForTimes1 (); mock.methodForTimes2 (); mock.methodForTimes3 (); mock.methodForTimes3 (); mock.methodForTimes3 (); nieuwe Verificaties () {{mock.methodForTimes3 (); minTimes = 1; maxTimes = 3; }}; }

In dit voorbeeld hebben we gedefinieerd dat precies twee aanroepen (niet één, niet drie, precies twee) van methodForTimes1 () moet worden gedaan met behulp van de lijn tijden = 2;.

Vervolgens hebben we het standaardgedrag gebruikt (als er geen herhalingsbeperking is gegeven minTimes = 1; wordt gebruikt) om te definiëren dat er ten minste één aanroep wordt gedaan methodForTimes2 ().

Ten slotte gebruiken minTimes = 1; gevolgd door maxTimes = 3; we bepaalden dat er tussen één en drie aanroepen zouden plaatsvinden methodForTimes3 ().

Houd er rekening mee dat beide minTimes en maxTimes kan worden gespecificeerd voor dezelfde verwachting, zolang minTimes wordt als eerste toegewezen. Aan de andere kant, keer kan alleen worden gebruikt.

2.5. Aangepaste argumentafstemming

Soms is het matchen van argumenten niet zo direct als het simpelweg specificeren van een waarde of het gebruik van enkele van de vooraf gedefinieerde hulpprogramma's (anyX of met X).

Voor die gevallen vertrouwt JMockit op Hamcrest's Matcher koppel. U hoeft alleen maar een matcher te definiëren voor het specifieke testscenario en die matcher te gebruiken met een withArgThat () bellen.

Laten we een voorbeeld bekijken voor het matchen van een specifieke klasse met een doorgegeven object:

openbare interface ExpectationsCollaborator {void methodForArgThat (Object o); } public class Model {public String getInfo () {return "info"; }} @Test public void testCustomArgumentMatching (@Mocked ExpectationsCollaborator mock) {new Expectations () {{mock.methodForArgThat (withArgThat (new BaseMatcher () {@Override public boolean matches (Object item) {return item instance of Model && "info". is gelijk aan (((Model) item) .getInfo ());} @Override public void descriptionTo (Beschrijving beschrijving) {}})); }}; mock.methodForArgThat (nieuw model ()); }

3. Terugkerende waarden

Laten we nu eens kijken naar de retourwaarden; Houd er rekening mee dat de volgende benaderingen alleen van toepassing zijn op Verwachtingen aangezien er geen retourwaarden kunnen worden gedefinieerd Verificaties.

3.1. Resultaat en rendement (...)

Als je JMockit gebruikt, heb je drie verschillende manieren om het verwachte resultaat van het aanroepen van een bespotte methode te definiëren. Van alle drie zullen we het nu hebben over de eerste twee (de eenvoudigste) die zeker 90% van de gevallen van dagelijks gebruik zullen dekken.

Deze twee zijn de resultaat veld en het retourneert (Object ...) methode:

  • Met de resultaat veld kunt u definiëren een retourwaarde voor elke niet-ongeldige terugkerende bespotte methode. Deze geretourneerde waarde kan ook een uitzondering zijn die moet worden gegenereerd (dit keer voor zowel niet-ongeldige als ongeldige retourmethoden).
    • Meerdere resultaat veldtoewijzingen kunnen worden gedaan om terug te keren meer dan één waarde voor meer dan één methode-aanroep (u kunt zowel retourwaarden als fouten combineren die moeten worden gegenereerd).
    • Hetzelfde gedrag zal worden bereikt bij het toewijzen aan resultaat een lijst of een reeks waarden (van hetzelfde type als het retourtype van de bespotte methode, GEEN uitzonderingen hier).
  • De retourneert (Object ...) methode is syntactische suiker voor het retourneren van meerdere waarden van dezelfde tijd.

Dit wordt gemakkelijker weergegeven met een codefragment:

openbare interface ExpectationsCollaborator {String methodReturnsString (); int methodReturnsInt (); } @Test openbare ongeldige testResultAndReturns (@Mocked ExpectationsCollaborator mock) {new Expectations () {{mock.methodReturnsString (); result = "foo"; resultaat = nieuwe uitzondering (); result = "balk"; retourneert ("foo", "bar"); mock.methodReturnsInt (); resultaat = nieuwe int [] {1, 2, 3}; resultaat = 1; }}; assertEquals ("Moet foo teruggeven", "foo", mock.methodReturnsString ()); probeer {mock.methodReturnsString (); fail ("Mag hier niet bereiken"); } catch (uitzondering e) {// NOOP} assertEquals ("Moet bar teruggeven", "bar", mock.methodReturnsString ()); assertEquals ("should return 1", 1, mock.methodReturnsInt ()); assertEquals ("Moet 2 retourneren", 2, mock.methodReturnsInt ()); assertEquals ("should return 3", 3, mock.methodReturnsInt ()); assertEquals ("Moet foo teruggeven", "foo", mock.methodReturnsString ()); assertEquals ("Moet bar teruggeven", "bar", mock.methodReturnsString ()); assertEquals ("should return 1", 1, mock.methodReturnsInt ()); }

In dit voorbeeld hebben we dat gedefinieerd voor de eerste drie oproepen naar methodReturnsString () het verwachte rendement is (in orde) "Foo", een uitzondering en "bar". We hebben dit bereikt met behulp van drie verschillende toewijzingen aan de resultaat veld.

Dan maar lijn 14hebben we gedefinieerd dat voor de vierde en vijfde oproep, "Foo" en "bar" moet worden geretourneerd met behulp van de retourneert (Object ...) methode.

Voor de methodReturnsInt () we hebben gedefinieerd lijn 13 om 1, 2 en ten slotte 3 te retourneren door een array met de verschillende resultaten toe te wijzen aan de resultaat veld en verder lijn 15 we hebben gedefinieerd om 1 terug te geven door een eenvoudige toewijzing aan de resultaat veld.

Zoals u kunt zien, zijn er verschillende manieren om retourwaarden voor bespotte methoden te definiëren.

3.2. Delegatoren

Om het artikel te beëindigen, behandelen we de derde manier om de geretourneerde waarde te definiëren: de Delegeren koppel. Deze interface wordt gebruikt voor het definiëren van meer complexe retourwaarden bij het definiëren van bespotte methoden.

We gaan een voorbeeld zien om simpelweg uit te leggen:

openbare interface ExpectationsCollaborator {int methodForDelegate (int i); } @Test public void testDelegate (@Mocked ExpectationsCollaborator mock) {new Expectations () {{mock.methodForDelegate (anyInt); result = new Delegate () {int delegate (int i) gooit Uitzondering {if (i <3) {return 5; } else {throw new Exception (); }}}; }}; assertEquals ("Moet 5 teruggeven", 5, mock.methodForDelegate (1)); probeer {mock.methodForDelegate (3); fail ("Mag hier niet bereiken"); } catch (uitzondering e) {}} 

De manier om een ​​delegator te gebruiken, is door er een nieuwe instantie voor te maken en deze toe te wijzen aan een geeft terug veld. In dit nieuwe geval moet u een nieuwe methode maken met dezelfde parameters en hetzelfde retourtype als de bespotte methode (u kunt er elke naam voor gebruiken). Gebruik binnen deze nieuwe methode elke gewenste implementatie om de gewenste waarde te retourneren.

In het voorbeeld hebben we een implementatie gedaan waarin 5 moet worden geretourneerd wanneer de waarde die wordt doorgegeven aan de bespotte methode kleiner is dan 3 en een uitzondering wordt anders gegenereerd (merk op dat we tijden = 2; zodat de tweede aanroep wordt verwacht omdat we het standaardgedrag verloren hebben door een retourwaarde te definiëren).

Het lijkt misschien nogal wat code, maar in sommige gevallen is dit de enige manier om het gewenste resultaat te bereiken.

4. Conclusie

Hiermee hebben we praktisch alles laten zien wat we nodig hebben om verwachtingen en verificaties te creëren voor onze dagelijkse tests.

We zullen natuurlijk meer artikelen over JMockit publiceren, dus blijf op de hoogte voor nog meer informatie.

En, zoals altijd, is de volledige implementatie van deze tutorial te vinden op het GitHub-project.

4.1. Artikelen in de serie

Alle artikelen uit de serie:

  • JMockit 101
  • Een gids voor JMockit-verwachtingen
  • JMockit geavanceerd gebruik

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