JMockit Advanced Usage

1. Bemutatkozás

Ebben a cikkben túllépünk a JMockit alapjain, és elkezdünk vizsgálni néhány speciális forgatókönyvet, például:

  • Hamisítás (vagy a Minta darab API)
  • A Dekapszulázás hasznossági osztály
  • Hogyan lehet több felületet gúnyolni, csak egy modell használatával
  • Hogyan lehet újból felhasználni az elvárásokat és az ellenőrzéseket

Ha meg akarja fedezni a JMockit alapjait, nézze meg a sorozat többi cikkét. A releváns linkeket az oldal alján találja.

2. Maven-függőség

Először hozzá kell adnunk a jmockit függőséget a projektünkhöz:

 org.jmockit jmockit 1.41 

Ezután folytatjuk a példákkal.

3. Privát módszerek / belső osztályok gúnyolódása

A magán módszerek vagy a belső osztályok kigúnyolása és tesztelése gyakran nem számít jó gyakorlatnak.

Az indoklás az, hogy ha magánszemélyek, akkor nem szabad őket közvetlenül tesztelni, mivel ők az osztály legbelsőbb béljei, de néha mégis meg kell tenni, különösen a régi kóddal való foglalkozáskor.

A JMockit használatával két lehetőség áll rendelkezésre ezek kezelésére:

  • A Minta darab API a valós megvalósítás megváltoztatásához (a második esethez)
  • A Dekapszulázás hasznossági osztály, bármelyik módszer közvetlen meghívása (első esetben)

Az összes következő példa a következő osztályra vonatkozik, és feltételezzük, hogy egy tesztosztályon futnak, ugyanazzal a konfigurációval, mint az első (a kód megismétlésének elkerülése érdekében):

nyilvános osztály AdvancedCollaborator {int i; private int privateField = 5; // az alapértelmezett konstruktor kihagyta a nyilvános AdvancedCollaborator (String string) dobja a Kivételt {i = string.length (); } public String methodThatCallsPrivateMethod (int i) {return privateMethod () + i; } public int methodThatReturnsThePrivateField () {return privateField; } private String privateMethod () {return "alapértelmezett:"; } osztály InnerAdvancedCollaborator {...}}

3.1. Faking With Minta darab

A JMockit Mockup API-ja támogatja a hamis implementációk vagy makettek. Jellemzően a minta darab néhány metódust és / vagy konstruktort céloz meg az osztályban, amelyet hamisítani kell, miközben a legtöbb más módszert és konstruktort nem módosítja. Ez lehetővé teszi az osztály teljes újraírását, így bármilyen módszer vagy konstruktor (bármilyen hozzáférés-módosítóval) megcélozható.

Lássuk, hogyan definiálhatjuk újra privateMethod () a Makett API használatával:

@RunWith (JMockit.class) nyilvános osztály AdvancedCollaboratorTest {@Tested private AdvancedCollaborator gúny; @Test public void testToMockUpPrivateMethod () {new MockUp () {@Mock private String privateMethod () {return "mocked:"; }}; Karakterlánc res = mock.methodThatCallsPrivateMethod (1); assertEquals ("csúfolt: 1", res); }}

Ebben a példában meghatározunk egy újat Minta darab a AdvancedCollaborator osztály a @Mock annotáció egy metódushoz egyező aláírással. Ezt követően az adott módszerre vonatkozó hívások delegálódnak a kigúnyoltunkra.

Ezt is felhasználhatjuk minta darab olyan osztály konstruktorának, amelynek specifikus argumentumokra vagy konfigurációra van szüksége a tesztek egyszerűsítése érdekében:

@Test public void testToMockUpDifficultConstructor () dobja a (z) {new MockUp () {@Mock public void $ init (Invocation invocation, String string) {((AdvancedCollaborator) invocation.getInvokedInstance ()) kivételt. I = 1; }}; AdvancedCollaborator coll = new AdvancedCollaborator (null); assertEquals (1, coll.i); }

Ebben a példában láthatjuk, hogy a konstruktor gúnyához meg kell gúnyolnia a $ init módszer. Átadhat egy extra típusú argumentumot Meghívás, amellyel hozzáférhet a csúfolt módszer meghívásával kapcsolatos információkhoz, beleértve azt a példányt is, amelyhez a meghívást végrehajtják.

3.2. Használni a Dekapszulázás Osztály

A JMockit tartalmaz egy teszt segédosztályt: a Dekapszulázás. Ahogy a neve is jelzi, egy objektum állapotának lezárására szolgál, és használatával egyszerűsítheti a tesztelést olyan mezők és módszerek elérésével, amelyekhez egyébként nem lehet hozzáférni.

Meghívhat egy módszert:

@Test public void testToCallPrivateMethodsDirectly () {Object value = Deencapsulation.invoke (mock, "privateMethod"); assertEquals ("alapértelmezett:", érték); }

Mezőket is beállíthat:

@Test public void testToSetPrivateFieldDirectly () {Deencapsulation.setField (gúny, "privateField", 10); assertEquals (10, mock.methodThatReturnsThePrivateField ()); }

És kérjen mezőket:

@Test public void testToGetPrivateFieldDirectly () {int érték = Deencapsulation.getField (gúny, "privateField"); assertEquals (5, érték); }

És hozzon létre új osztályok példányokat:

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

Még a belső osztályok új példányai:

@Test public void testToCreateNewInnerClassInstanceDirectly () {InnerCollaborator inner = Deencapsulation .newInnerInstance (InnerCollaborator.class, gúny); assertNotNull (belső); }

Mint láthatja, a Dekapszulázás osztály rendkívül hasznos a légzáró osztályok tesztelésénél. Ilyen lehet például egy olyan osztály függőségeinek beállítása, amely használ @Autowired feliratok a privát mezőkön, és nincsenek beállítóik számukra, vagy a belső osztályok teszteléséhez anélkül, hogy a konténerosztály nyilvános felületétől kellene függenie.

4. Több interfész gúnyolása ugyanabban a gúnyban

Tegyük fel, hogy tesztelni akar egy - még nem megvalósított - osztályt, de pontosan tudja, hogy több interfészt is megvalósít.

Általában nem tudná tesztelni az említett osztályt, mielőtt végrehajtaná, de a JMockit használatával lehetősége van arra, hogy előzetesen előkészítse a teszteket úgy, hogy egynél több felületet csúfol egy mock objektum segítségével.

Ez elérhető generikus módszerek használatával és egy olyan típus definiálásával, amely több interfészt kiterjeszt. Ez az általános típus vagy meghatározható egy teljes tesztosztályra, vagy csak egy vizsgálati módszerre.

Például létrehozunk egy csúfot az interfészek számára Lista és Hasonló két út:

@RunWith (JMockit.class) nyilvános osztály AdvancedCollaboratorTest> {@Mocked private MultiMock multiMock; @Test public void testOnClass () {new Expectations () {{multiMock.get (5); eredmény = "foo"; multiMock.compareTo ((List) bármely); eredmény = 0; }}; assertEquals ("foo", multiMock.get (5)); assertEquals (0, multiMock.compareTo (új ArrayList ())); } @Test public > void testOnMethod (@Mocked M gúny) {new Expectations () {{mock.get (5); eredmény = "foo"; mock.compareTo ((List) any); eredmény = 0; }}; assertEquals ("foo", gúny.get (5)); assertEquals (0, mock.compareTo (új ArrayList ())); }}

Amint a 2. sorban láthatja, meghatározhatunk egy új teszttípust az egész tesztre azáltal, hogy az osztály nevén általánosakat használunk. Úgy, MultiMock típusként lesz elérhető, és a JMockit bármelyik kommentárjának használatával létrehozhatsz neki gúnyokat.

A 7-től 18-ig terjedő sorokban láthatunk egy példát, amely az egész tesztosztályra definiált többosztályos modellt használja.

Ha csak egy tesztre van szüksége a több interfészes modellre, akkor ezt úgy érheti el, hogy meghatározza a metódus aláírásánál az általános típust, és az új generikus modell új argumentumát adja át a teszt metódus argumentumának. A 20–32. Sorokban példát láthatunk erre ugyanazon tesztelt viselkedés esetén, mint az előző tesztben.

5. Az elvárások és az igazolások újrafelhasználása

Végül az osztályok tesztelésekor olyan esetekkel találkozhat, amelyekben ugyanazt ismételgeti Elvárások és / vagy Ellenőrzések újra és újra. Ennek megkönnyítése érdekében mindkettőt könnyedén felhasználhatja.

Egy példával fogjuk elmagyarázni (az osztályokat használjuk Modell, munkatárs, és Előadó a JMockit 101 cikkünkből):

@RunWith (JMockit.class) public class ReusingTest {@Injectable private Collaborator munkatárs; @Mocked private model model; @Tesztelt privát előadóművész; @A nyilvános void beállítása előtt () {new Expectations () {{model.getInfo (); eredmény = "foo"; minTimes = 0; munkatárs.együttműködés ("foo"); eredmény = igaz; minTimes = 0; }}; } @Test public void testWithSetup () {performer.perform (model); verTrueCalls (1); } védett void verTrueCalls (int hívások) {új ellenőrzések () {{munkatárs.fogad (igaz); idők = hívások; }}; } final class TrueCallsVerification kiterjeszti az ellenőrzést {public TrueCallsVerification (int hívások) {munkatárs.receive (igaz); idők = hívások; }} @Test public void testWithFinalClass () {performer.perform (modell); új TrueCallsVerification (1); }}

Ebben a példában a 15-18 közötti sorokban láthatja, hogy minden tesztre elvárást készítünk, így model.getInfo () mindig visszatér „Foo” és azért munkatárs.együttműködni() hogy mindig elvárják „Foo” mint érv és visszatérő igaz. Tettük a minTimes = 0 tehát nem jelenik meg kudarc, amikor nem használják őket tesztekben.

Emellett létrehoztunk egy módszert verTrueCalls (int) az ellenőrzések egyszerűsítése a munkatárs.fogadás (logikai érték) metódus, amikor az átadott argumentum igaz.

Végül új típusú specifikus elvárásokat és ellenőrzéseket is létrehozhat, amelyek bármelyikét kibővítik Elvárások vagy Ellenőrzések osztályok. Ezután definiáljon egy konstruktort, ha konfigurálnia kell a viselkedést, és egy új típusú példányt kell létrehoznia a tesztben, ahogy mi tesszük a 33 és 43 közötti sorokban.

6. Következtetés

A JMockit sorozat ezen részével több haladó témát érintettünk, amelyek mindenképpen segítenek a mindennapi gúnyolódásban és tesztelésben.

Lehet, hogy még több cikket készítünk a JMockit-ról, ezért figyeljen arra, hogy még többet tudjon meg.

És mint mindig, ennek az oktatóanyagnak a teljes megvalósítása megtalálható a GitHubon.

6.1. A sorozat cikkei

A sorozat összes cikke:

  • JMockit 101
  • Útmutató a JMockit elvárásaihoz
  • JMockit Advanced Usage

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