Pokročilé použitie JMockit

1. Úvod

V tomto článku pôjdeme nad rámec základov JMockit a začneme sa pozerať na niektoré pokročilé scenáre, napríklad:

  • Falošné (alebo MockUp API)
  • The Odpadnutie úžitková trieda
  • Ako sa vysmievajú viacerým rozhraniam pomocou iba jedného vysmievaného
  • Ako znovu použiť očakávania a overenia

Ak chcete zistiť základné informácie o JMockite, prečítajte si ďalšie články z tejto série. Príslušné odkazy nájdete v dolnej časti stránky.

2. Závislosť od Maven

Najskôr do nášho projektu budeme musieť pridať závislosť jmockit:

 org.jmockit jmockit 1,41 

Ďalej budeme pokračovať v príkladoch.

3. Súkromné ​​metódy / zosmiešňovanie vnútorných tried

Vymýšľanie a testovanie súkromných metód alebo interných kurzov sa často nepovažuje za dobrú prax.

Zdôvodňuje sa to tým, že ak sú súkromné, nemali by sa testovať priamo, pretože sú najvnútornejšou vnútornosťou triedy, ale niekedy to treba ešte urobiť, najmä pri narábaní so starým kódom.

S JMockitom máte dve možnosti, ako tieto vyriešiť:

  • The MockUp API na zmenu skutočnej implementácie (pre druhý prípad)
  • The Odpadnutie trieda nástrojov, na priame volanie ľubovoľnej metódy (pre prvý prípad)

Všetky nasledujúce príklady budú vykonané pre nasledujúcu triedu a budeme predpokladať, že sú spustené na testovacej triede s rovnakou konfiguráciou ako tá prvá (aby sa zabránilo opakovaniu kódu):

verejná trieda AdvancedCollaborator {int i; private int privateField = 5; // predvolený konštruktor vynechaný public AdvancedCollaborator (reťazec reťazcov) vyvolá výnimku {i = string.length (); } public String methodThatCallsPrivateMethod (int i) {return privateMethod () + i; } public int methodThatReturnsThePrivateField () {return privateField; } private String privateMethod () {return "default:"; } trieda InnerAdvancedCollaborator {...}}

3.1. Falošné s MockUp

Mockup API spoločnosti JMockit poskytuje podporu pre vytváranie falošných implementácií alebo makety. Spravidla a maketa zacieli na niekoľko metód a / alebo konštruktorov v triede, ktoré majú byť fingované, zatiaľ čo väčšinu ostatných metód a konštruktorov ponechá neupravených. To umožňuje úplné prepísanie triedy, takže je možné zacieliť na ktorúkoľvek metódu alebo konštruktor (s akýmkoľvek modifikátorom prístupu).

Pozrime sa, ako to môžeme nanovo definovať privateMethod () pomocou Mockup API:

@RunWith (JMockit.class) verejná trieda AdvancedCollaboratorTest {@Testované súkromné ​​AdvancedCollaborator falošné; @Test public void testToMockUpPrivateMethod () {new MockUp () {@Mock private String privateMethod () {return "mocked:"; }}; Reťazec res = mock.methodThatCallsPrivateMethod (1); assertEquals ("zosmiešňované: 1", res); }}

V tomto príklade definujeme nový MockUp pre AdvancedCollaborator triedy pomocou @Mock anotácia metódy so zhodným podpisom. Potom budú hovory na túto metódu delegované na našu vysmievanú.

Môžeme to použiť aj na maketa konštruktor triedy, ktorá na zjednodušenie testov potrebuje konkrétne argumenty alebo konfiguráciu:

@Test public void testToMockUpDifficultConstructor () vyvolá výnimku {new MockUp () {@Mock public void $ init (vyvolanie vyvolania, reťazec reťazca) {((AdvancedCollaborator) vyvolanie.getInvokedInstance ()). I = 1; }}; AdvancedCollaborator coll = nový AdvancedCollaborator (null); assertEquals (1, kol. i); }

V tomto príklade vidíme, že pri posmievaní konštruktéra sa musíte vysmievať $ init metóda. Môžete vložiť ďalší argument typu Vyvolanie, pomocou ktorého máte prístup k informáciám o vyvolaní vysmiatej metódy vrátane inštancie, do ktorej sa vyvolanie vykonáva.

3.2. Pomocou Odpadnutie Trieda

JMockit obsahuje testovaciu utilitu triedy: Odpadnutie. Ako naznačuje jeho názov, slúži na deenkapsuláciu stavu objektu a pomocou neho môžete testovanie zjednodušiť prístupom k poliam a metódam, ku ktorým by sa inak nedalo dostať.

Môžete vyvolať metódu:

@Test public void testToCallPrivateMethodsDirectly () {Object value = Deencapsulation.invoke (mock, "privateMethod"); assertEquals ("predvolené:", hodnota); }

Môžete tiež nastaviť polia:

@Test public void testToSetPrivateFieldDirectly () {Deencapsulation.setField (falošný, "privateField", 10); assertEquals (10, mock.methodThatReturnsThePrivateField ()); }

A získajte polia:

@Test public void testToGetPrivateFieldDirectly () {int value = Deencapsulation.getField (falošný, "privateField"); assertEquals (5, hodnota); }

A vytvorte nové inštancie tried:

@Test public void testToCreateNewInstanceDirectly () {AdvancedCollaborator coll = Deencapsulation .newInstance (AdvancedCollaborator.class, "foo"); assertEquals (3, kol. i); }

Aj nové inštancie vnútorných tried:

@Test public void testToCreateNewInnerClassInstanceDirectly () {InnerCollaborator internal = Deencapsulation .newInnerInstance (InnerCollaborator.class, mock); assertNotNull (vnútorný); }

Ako vidíte, Odpadnutie triedy je mimoriadne užitočná pri testovaní tried vzduchotesnosti. Jedným príkladom môže byť nastavenie závislostí triedy, ktorá používa @Autowired anotácie na súkromných poliach a nemá pre ne nastavovače, ani na testovanie vnútorných tried jednotiek bez toho, aby museli závisieť od verejného rozhrania svojej triedy kontajnerov.

4. Vysmievanie viacerých rozhraní v jednom rovnakom vysmievaní

Predpokladajme, že chcete otestovať triedu - zatiaľ neimplementovanú - ale určite viete, že bude implementovať niekoľko rozhraní.

Zvyčajne by ste neboli schopní otestovať uvedenú triedu pred jej implementáciou, ale s JMockitom máte možnosť pripraviť si testy vopred tak, že sa budete posmievať viac ako jednému rozhraniu pomocou jedného simulovaného objektu.

To sa dá dosiahnuť použitím generík a definovaním typu, ktorý rozširuje niekoľko rozhraní. Tento všeobecný typ možno definovať buď pre celú testovaciu triedu, alebo iba pre jednu testovaciu metódu.

Napríklad vytvoríme simuláciu rozhraní Zoznam a Porovnateľné dve cesty:

@RunWith (JMockit.class) verejná trieda AdvancedCollaboratorTest> {@Mocked private MultiMock multiMock; @Test public void testOnClass () {new Expectations () {{multiMock.get (5); výsledok = "foo"; multiMock.compareTo ((Zoznam) akýkoľvek); výsledok = 0; }}; assertEquals ("foo", multiMock.get (5)); assertEquals (0, multiMock.compareTo (nový ArrayList ())); } @Test verejné > void testOnMethod (@Mocked M mock) {new Expectations () {{mock.get (5); výsledok = "foo"; mock.compareTo ((Zoznam) akýkoľvek); výsledok = 0; }}; assertEquals ("foo", mock.get (5)); assertEquals (0, mock.compareTo (nový ArrayList ())); }}

Ako vidíte na riadku 2, môžeme definovať nový typ testu pre celý test použitím generík v názve triedy. Tým smerom, MultiMock bude k dispozícii ako typ a budete si preň môcť vytvárať zosmiešňovanie pomocou ktorejkoľvek z anotácií JMockit.

V riadkoch od 7 do 18 môžeme vidieť príklad, ktorý používa simuláciu viactriedy definovanej pre celú testovaciu triedu.

Ak potrebujete simuláciu s viacerými rozhraniami iba na jeden test, môžete to dosiahnuť definovaním generického typu v podpise metódy a odovzdaním novej simulácie tohto nového generického typu ako argumentu testovacej metódy. V riadkoch 20 až 32 môžeme vidieť príklad toho, že tak môžeme urobiť pre rovnaké testované správanie ako v predchádzajúcom teste.

5. Opätovné použitie očakávaní a overení

Nakoniec sa pri testovaní hodín môžete stretnúť s prípadmi, keď opakujete to isté Očakávania a / alebo Overenia znova a znova. Aby ste to uľahčili, môžete obidve ľahko opätovne použiť.

Vysvetlíme to na príklade (používame triedy Model, Spolupracovníka Účinkujúci z nášho článku JMockit 101):

@RunWith (JMockit.class) verejná trieda ReusingTest {@Injectable private Collaborator spolupracovník; @Mocked model súkromného modelu; @ Testovaný súkromný umelec; @ Pred public void setup () {new Expectations () {{model.getInfo (); výsledok = "foo"; minTimes = 0; spolupracovník.spolupráca („foo“); výsledok = pravda; minTimes = 0; }}; } @Test public void testWithSetup () {performer.perform (model); verifyTrueCalls (1); } protected void verifyTrueCalls (int calls) {new Verifications () {{cooperator.receive (true); časy = hovory; }}; } konečná trieda TrueCallsVerification rozširuje overenia {public TrueCallsVerification (int hovory) {spolupracujúci.receív (true); časy = hovory; }} @Test public void testWithFinalClass () {performer.perform (model); nové TrueCallsVerification (1); }}

V tomto príklade môžete vidieť v riadkoch od 15 do 18, že pripravujeme očakávanie pre každý test model.getInfo () vždy sa vráti „Foo“ a pre spolupracovník.spolupracovať() vždy očakávať „Foo“ ako argument a návrat pravda. Dali sme minTimes = 0 vyhlásenie, takže sa neobjavia žiadne zlyhania, keď ich vlastne nepoužívate v testoch.

Tiež sme vytvorili metódu verifyTrueCalls (int) - zjednodušiť overovanie na - spolupracovník.prijať (logická hodnota) metóda, keď je zadaný argument pravda.

Na záver môžete tiež vytvoriť nové typy konkrétnych očakávaní a overení, ktoré iba rozšíria ktorékoľvek z nich Očakávania alebo Overenia triedy. Potom definujete konštruktor, ak potrebujete nakonfigurovať správanie a vytvoriť novú inštanciu uvedeného typu v teste, ako to robíme v riadkoch od 33 do 43.

6. Záver

Týmto dielom série JMockit sme sa dotkli niekoľkých pokročilých tém, ktoré vám určite pomôžu pri každodennom posmievaní sa a testovaní.

Možno urobíme viac článkov o JMockite, takže buďte pripravení, aby ste sa dozvedeli ešte viac.

A ako vždy, úplnú implementáciu tohto tutoriálu nájdete na GitHub.

6.1. Články v seriáli

Všetky články zo série:

  • JMockit 101
  • Sprievodca očakávaním JMockit
  • Pokročilé použitie JMockit

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