Mockito vs EasyMock vs JMockit

1. Uvod

1.1. Pregled

U ovom postu ćemo razgovarati o ruganje: što je to, zašto ga koristiti i nekoliko primjera kako se ismijavati isti testni slučaj koristeći neke od najčešće korištenih podrugljivih knjižnica za Javu.

Počet ćemo s nekim formalnim / poluformalnim definicijama podrugljivih koncepata; tada ćemo predstaviti slučaj na testiranju, slijediti primjere za svaku knjižnicu i na kraju donijeti neke zaključke. Odabrane knjižnice su Mockito, EasyMock i JMockit.

Ako smatrate da već znate osnove ruganja, možda možete preskočiti točku 2 bez čitanja sljedeće tri točke.

1.2. Razlozi za upotrebu podsmijeha

Počet ćemo pretpostavljati da već kodirate slijedeći neku pokretačku razvojnu metodologiju usredotočenu na testove (TDD, ATDD ili BDD). Ili jednostavno da želite stvoriti test za postojeću klasu koja se oslanja na ovisnosti kako bi postigla svoju funkcionalnost.

U svakom slučaju, kada jedinstveno testiramo klasu, mi to želimo testirajte samo njegovu funkcionalnost, a ne onu ovisnosti (bilo zato što vjerujemo njihovoj provedbi ili zato što ćemo ga sami testirati).

Da bismo to postigli, predmetu koji se testira moramo pružiti zamjenu koju možemo kontrolirati za tu ovisnost. Na ovaj način možemo forsirati ekstremne povratne vrijednosti, izbacivanje izuzetaka ili jednostavno smanjiti vremenske metode na fiksnu povratnu vrijednost.

Ova kontrolirana zamjena je oponašanje, a pomoći će vam da pojednostavite kodiranje testa i smanjite vrijeme izvršavanja testa.

1.3. Lažni koncepti i definicija

Pogledajmo četiri definicije iz članka Martina Fowlera koji sažima osnove koje bi svi trebali znati o lažnim porukama:

  • Lutke predmeti se prenose, ali se zapravo nikada ne koriste. Obično se koriste samo za popunjavanje popisa parametara.
  • Lažni objekti imaju funkcionalne implementacije, ali obično koriste prečac koji ih čini neprikladnima za proizvodnju (dobar primjer je baza podataka u memoriji).
  • Stubs pružite pripremljene odgovore na pozive upućene tijekom testa, obično uopće ne reagirajući ni na što izvan onoga što je programirano za test. Stubs također mogu snimati informacije o pozivima, poput kvara pristupnika e-pošte koji pamti poruke koje je "poslao" ili možda samo koliko je poruka "poslao".
  • Ismijava su ono o čemu ovdje govorimo: objekti unaprijed programirani s očekivanjima koji čine specifikaciju poziva koje se očekuje da će primiti.

1.4 Rugati se ili ne rugati se: To je pitanje

Ne mora se sve ismijavati. Ponekad je bolje napraviti test integracije jer ismijavanje te metode / značajke samo radi za malo stvarne koristi. U našem testnom slučaju (koji će biti prikazan u sljedećoj točki) koji bi testirao LoginDao.

The LoginDao bi za pristup DB-u koristio neku biblioteku treće strane, a ismijavanje bi se sastojalo samo od osiguranja da su parametri pripremljeni za poziv, ali svejedno ćemo morati testirati da poziv vraća podatke koje smo željeli.

Iz tog razloga neće biti uključen u ovaj primjer (iako bismo mogli napisati i jedinični test s lažnim pozivima za pozive knjižnice treće strane I test integracije s DBUnit za testiranje stvarnih performansi biblioteke treće strane).

2. Test slučaj

Imajući na umu sve u prethodnom odjeljku, predložimo sasvim tipičan testni slučaj i kako ćemo ga testirati pomoću lažnih (kada ima smisla koristiti lažne). To će nam pomoći da imamo zajednički scenarij za kasnije da bismo mogli usporediti različite podrugljive knjižnice.

2.1 Predloženi slučaj

Predloženi test bit će postupak prijave u aplikaciju s višeslojnom arhitekturom.

Zahtjevom za prijavu bavit će se kontroler koji koristi uslugu koja koristi DAO (koji traži vjerodajnice korisnika na DB-u). Nećemo se produbljivati ​​previše u implementaciji svakog sloja i više ćemo se usredotočiti na interakcije između komponenata svakog sloja.

Ovim putem ćemo imati LoginController, a LoginService i a PrijavaDAO. Pogledajmo dijagram za pojašnjenje:

2.2 Provedba

Sada ćemo slijediti implementaciju koja se koristi za testni slučaj, kako bismo mogli razumjeti što se (ili što bi se trebalo dogoditi) na testovima.

Počet ćemo s modelom koji se koristi za sve operacije, Korisnički obrazac, koji će sadržavati samo korisničko ime i lozinku (za pojednostavljenje koristimo modifikatore javnog pristupa) i gettersku metodu za Korisničko ime polje za dopuštanje ruganja za to svojstvo:

javna klasa UserForm {lozinka javnog niza; korisničko ime javnog niza; javni String getUsername () {return korisničko ime; }}

Slijedimo PrijavaDAO, to će biti bez funkcionalnosti, jer samo želimo da njegove metode budu tamo, kako bismo im se mogli rugati po potrebi:

javna klasa LoginDao {javna int prijava (UserForm userForm) {return 0; }}

LoginDao će se koristiti LoginService u svojoj prijaviti se metoda. LoginService također će imati setCurrentUser metoda koja se vraća poništiti da isproba to ruganje.

javna klasa LoginService {private LoginDao loginDao; private String currentUser; javna logička prijava (UserForm userForm) {assert null! = userForm; int loginResults = loginDao.login (userForm); prekidač (loginResults) {slučaj 1: povratak true; zadana vrijednost: return false; }} javna void setCurrentUser (korisničko ime niza) {if (null! = korisničko ime) {this.currentUser = korisničko ime; }}}

Konačno, LoginController koristit ću LoginService za svoje prijaviti se metoda. To će uključivati:

  • slučaj u kojem se neće obavljati pozivi izrugivane službe.
  • slučaj u kojem će biti pozvana samo jedna metoda.
  • slučaj u kojem će biti pozvane sve metode.
  • slučaj u kojem će se testirati izbacivanje.
javna klasa LoginController {javna LoginService loginService; javna prijava u niz (UserForm userForm) {if (null == userForm) {return "ERROR"; } else {logički zapisano; pokušajte {logged = loginService.login (userForm); } catch (Iznimka e) {return "POGREŠKA"; } if (prijavljeno) {loginService.setCurrentUser (userForm.getUsername ()); vratite "OK"; } else {vratiti "KO"; }}}}

Sad kad smo vidjeli što pokušavamo testirati, pogledajmo kako ćemo se rugati sa svakom knjižnicom.

3. Postavljanje testa

3.1 Mockito

Za Mockito koristit ćemo verziju 2.8.9.

Najlakši način stvaranja i korištenja lažiranja je putem @Oponašanje i @InjectMocks bilješke. Prvi će stvoriti podsmijeh za klasu koja se koristi za definiranje polja, a drugi će pokušati ubrizgati spomenute stvorene podsmjehe u anotirani lažni obrazac.

Postoji više napomena poput @Špijun koji vam omogućuje stvaranje djelomičnog lažnog predstavljanja (lažnog korištenja koje koristi uobičajenu implementaciju u neismijanim metodama).

To je rečeno, morate nazvati MockitoAnnotations.initMocks (ovo) prije izvođenja bilo kakvih testova koji bi koristili spomenute izrugivanja da bi cijela ta "magija" djelovala. To se obično radi u a @Prije anotirana metoda. Također možete koristiti MockitoJUnitRunner.

javna klasa LoginControllerTest {@Mock private LoginDao loginDao; @Spy @InjectMocks privatni LoginService spiedLoginService; @Mock private LoginService loginService; @InjectMocks privatni LoginController loginController; @Prije javne void setUp () {loginController = novi LoginController (); MockitoAnnotations.initMocks (ovo); }}

3.2 EasyMock

Za EasyMock koristit ćemo verziju 3.4 (Javadoc). Imajte na umu da s EasyMock-om morate nazvati da bi makete počele "raditi" EasyMock.replay (lažno) na svakoj ispitnoj metodi ili ćete dobiti iznimku.

Izmjene i testirane klase također se mogu definirati putem bilješki, ali u ovom ćemo slučaju, umjesto pozivanja statičke metode za rad, koristiti EasyMockRunner za ispitnu klasu.

Izrugivanja se stvaraju pomoću @Oponašanje bilješka i testirani objekt s @TestSubject jedan (koji će svoje ovisnosti ubrizgati iz stvorenih lažnih slika). Testirani objekt mora biti izrađen u liniji.

@RunWith (EasyMockRunner.class) javna klasa LoginControllerTest {@Mock private LoginDao loginDao; @Mock private LoginService loginService; @TestSubject private LoginController loginController = novi LoginController (); }

3.3. JMockit

Za JMockit koristit ćemo verziju 1.24 (Javadoc) jer inačica 1.25 još nije objavljena (barem dok je ovo pisala).

Postavljanje za JMockit jednostavno je kao i kod Mockita, s tim da ne postoji posebna napomena za djelomične lažne prezentacije (a zapravo i nije potrebna) i da morate koristiti JMockit kao test trkač.

Ruganja se definiraju pomoću @Injekcijski napomena (koja će stvoriti samo jednu lažnu instancu) ili sa @Mocked napomena (koja će stvoriti podsmijehe za svaku instancu klase označenog polja).

Testirana se instanca kreira (i ubrizgavaju se izružene ovisnosti) pomoću @ Testirano bilješka.

@RunWith (JMockit.class) javna klasa LoginControllerTest {@Injectable private LoginDao loginDao; @Injekcijski privatni LoginService loginService; @ Testirano privatno LoginController loginController; }

4. Provjera nema poziva na ruganje

4.1. Mockito

Za provjeru je li lažna primanje poziva u Mockitu, imate metodu verifyZeroInteractions () koji prihvaća podsmijeh.

@Test public void assertThatNoMethodHasBeenCalled () {loginController.login (null); Mockito.verifyZeroInteractions (loginService); }

4.2. EasyMock

Da biste potvrdili da lažni podatak nije primio pozive, jednostavno ne specificirate ponašanje, ponovite lažni prikaz i na kraju potvrdite ga.

@Test public void assertThatNoMethodHasBeenCalled () {EasyMock.replay (loginService); loginController.login (null); EasyMock.verify (loginService); }

4.3. JMockit

Da biste potvrdili da lažni primatelja nije dobio poziv, jednostavno ne navodite očekivanja za taj lažni obrazac i napravite a FullVerifications (lažno) za spomenuto izrugivanje.

@Test public void assertThatNoMethodHasBeenCalled () {loginController.login (null); nove FullVerifications (loginService) {}; }

5. Utvrđivanje poziva s podsmijehom i potvrda poziva za ismijavanje

5.1. Mockito

Za podrugljivi pozivi metode, možeš koristiti Mockito.when (mock.method (args)). ThenReturn (vrijednost). Ovdje možete vratiti različite vrijednosti za više poziva, dodajući ih kao više parametara: thenReturn (vrijednost1, vrijednost2, vrijednost-n,…).

Imajte na umu da se ovom sintaksom ne možete rugati metodama vraćanja praznina. U navedenim ćete slučajevima koristiti provjeru spomenute metode (kao što je prikazano u retku 11).

Za provjera poziva na podsmijeh koji možete koristiti Mockito.verify (mock) .method (args) a također možete provjeriti da više nije bilo poziva na lažni uporab verifyNoMoreInteractions (lažno).

Za provjeravanje argumenata, možete proslijediti određene vrijednosti ili koristiti unaprijed definirane podudarnosti poput bilo koji (), anyString (), anyInt (). Postoji puno više takvih vrsta podudaranja, pa čak i mogućnost definiranja vaših podudaranja, što ćemo vidjeti u sljedećim primjerima.

@Test public void assertTwoMethodsHaveBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; Mockito.when (loginService.login (userForm)). ThenReturn (true); String login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); Mockito.verify (loginService) .login (userForm); Mockito.verify (loginService) .setCurrentUser ("foo"); } @Test public void assertOnlyOneMethodHasBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; Mockito.when (loginService.login (userForm)). ThenReturn (false); String login = loginController.login (userForm); Assert.assertEquals ("KO", prijava); Mockito.verify (loginService) .login (userForm); Mockito.verifyNoMoreInteractions (loginService); }

5.2. EasyMock

Za podrugljivi pozivi metode, ti koristiš EasyMock.expect (mock.method (args)). AndReturn (vrijednost).

Za provjera poziva za podsmijeh, možete koristiti EasyMock.verify (lažno), ali to morate nazvati uvijek poslije pozivajući EasyMock.replay (lažno).

Za provjeravanje argumenata, možete proslijediti određene vrijednosti ili ste unaprijed definirali podudaranja poput isA(Class.class), anyString (), anyInt (), i puno više takvih vrsta podudaranja i opet mogućnost definiranja vaših podudaranja.

@Test public void assertTwoMethodsHaveBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; EasyMock.expect (loginService.login (userForm)). AndReturn (true); loginService.setCurrentUser ("foo"); EasyMock.replay (loginService); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); EasyMock.verify (loginService); } @Test public void assertOnlyOneMethodHasBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; EasyMock.expect (loginService.login (userForm)). AndReturn (false); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("KO", prijava); EasyMock.verify (loginService); }

5.3. JMockit

S JMockitom definirali ste korake za testiranje: snimanje, ponovna reprodukcija i provjera.

Snimiti se vrši u novom Očekivanja () {{}} blok (u koji možete definirati radnje za nekoliko ismijavanja), ponoviti se vrši jednostavnim pozivanjem metode testirane klase (koja bi trebala pozvati neki izrugivani objekt), i verifikacija se radi unutar novog Potvrde () {{}} blok (u koji možete definirati provjere za nekoliko podsmijeha).

Za podrugljivi pozivi metode, možeš koristiti mock.method (args); rezultat = vrijednost; unutar bilo kojeg Očekivanja blok. Ovdje možete vratiti različite vrijednosti za više poziva samo pomoću vraća (vrijednost1, vrijednost2,…, valuen); umjesto rezultat = vrijednost;.

Za provjera poziva za podsmijeh možete koristiti nove potvrde() {{mock.call (vrijednost)}} ili nove provjere (lažno) {{}} za provjeru svakog prethodno očekivanog poziva.

Za provjeravanje argumenata, možete proslijediti određene vrijednosti ili imate unaprijed definirane vrijednosti poput bilo koji, anyString, bilo kojiDugo, i puno više takvih vrsta posebnih vrijednosti i opet mogućnost definiranja vaših podudaranja (to moraju biti Hamcrest podudaranja).

@Test public void assertTwoMethodsHaveBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; nova Očekivanja () {{loginService.login (userForm); rezultat = točno; loginService.setCurrentUser ("foo"); }}; Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); nove FullVerifications (loginService) {}; } @Test public void assertOnlyOneMethodHasBeenCalled () {UserForm userForm = novi UserForm (); userForm.username = "foo"; nova Očekivanja () {{loginService.login (userForm); rezultat = netačno; // nema očekivanja za setCurrentUser}}; String login = loginController.login (userForm); Assert.assertEquals ("KO", prijava); nove FullVerifications (loginService) {}; }

6. Podrugljivo bacanje izuzetaka

6.1. Mockito

Iznimno bacanje može se ismijati pomoću . thenThrow (ExceptionClass.class) poslije Mockito.when (mock.method (args)).

@Test public void mockExceptionThrowin () {UserForm userForm = novi UserForm (); Mockito.when (loginService.login (userForm)). ThenThrow (IllegalArgumentException.class); Niz login = loginController.login (userForm); Assert.assertEquals ("POGREŠKA", prijava); Mockito.verify (loginService) .login (userForm); Mockito.verifyZeroInteractions (loginService); }

6.2. EasyMock

Iznimno bacanje može se ismijati pomoću .andThrow (nova klasa iznimke ()) nakon an EasyMock.expect (…) poziv.

@Test public void mockExceptionThrowing () {UserForm userForm = novi UserForm (); EasyMock.expect (loginService.login (userForm)). AndThrow (novi IllegalArgumentException ()); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("POGREŠKA", prijava); EasyMock.verify (loginService); }

6.3. JMockit

Podrugljivo bacanje izuzetaka s JMockitom je posebno lako. Samo vratite iznimku kao rezultat izrugivanog poziva metode umjesto "normalnog" povratka.

@Test public void mockExceptionThrowing () {UserForm userForm = novi UserForm (); nova Očekivanja () {{loginService.login (userForm); rezultat = novi IllegalArgumentException (); // nema očekivanja za setCurrentUser}}; String login = loginController.login (userForm); Assert.assertEquals ("POGREŠKA", prijava); nove FullVerifications (loginService) {}; }

7. Ruganje objektu kako bi se prošao

7.1. Mockito

Možete stvoriti lažni obrazac koji će se proslijediti kao argument za poziv metode. S Mockitom to možete učiniti s jednom linijom.

@Test public void mockAnObjectToPassAround () {UserForm userForm = Mockito.when (Mockito.mock (UserForm.class) .getUsername ()). ThenReturn ("foo"). GetMock (); Mockito.when (loginService.login (userForm)). ThenReturn (true); String login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); Mockito.verify (loginService) .login (userForm); Mockito.verify (loginService) .setCurrentUser ("foo"); }

7.2. EasyMock

Mockovi se mogu stvarati u skladu s EasyMock.mock (Class.class). Poslije možete koristiti EasyMock.expect (mock.method ()) pripremiti ga za izvršenje, uvijek se sjećajući da ga nazovem EasyMock.replay (lažno) prije nego što ga upotrijebite.

@Test public void mockAnObjectToPassAround () {UserForm userForm = EasyMock.mock (UserForm.class); EasyMock.expect (userForm.getUsername ()). AndReturn ("foo"); EasyMock.expect (loginService.login (userForm)). AndReturn (true); loginService.setCurrentUser ("foo"); EasyMock.replay (userForm); EasyMock.replay (loginService); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); EasyMock.verify (userForm); EasyMock.verify (loginService); }

7.3. JMockit

Da biste ismijali objekt samo za jednu metodu, možete ga jednostavno podmiriti kao parametar testnoj metodi. Tada možete stvoriti očekivanja kao i kod bilo koje druge lažne slike.

@Test public void mockAnObjectToPassAround (@Mocked UserForm userForm) {nova očekivanja () {{userForm.getUsername (); rezultat = "foo"; loginService.login (userForm); rezultat = točno; loginService.setCurrentUser ("foo"); }}; Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); nove FullVerifications (loginService) {}; nove FullVerifications (userForm) {}; }

8. Usklađivanje prilagođenih argumenata

8.1. Mockito

Ponekad podudaranje argumenata za izrugivane pozive mora biti malo složenije od samo fiksne vrijednosti ili anyString (). U tom slučaju Mockito ima klasu podudaranja koja se koristi sa argThat (ArgumentMatcher).

@Test public void argumentMatching () {UserForm userForm = novi UserForm (); userForm.username = "foo"; // zadana podudarnost Mockito.when (loginService.login (Mockito.any (UserForm.class))). thenReturn (true); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); Mockito.verify (loginService) .login (userForm); // složeno podudaranje Mockito.verify (loginService) .setCurrentUser (ArgumentMatchers.argThat (new ArgumentMatcher () {@Override public boolean matches (String argument) {return argument.startsWith ("foo");}})); }

8.2. EasyMock

Prilagođeno podudaranje argumenata malo je složenije s EasyMockom jer trebate stvoriti statičku metodu u kojoj kreirate stvarno podudaranje, a zatim prijavite s EasyMock.reportMatcher (IArgumentMatcher).

Jednom kada se stvori ova metoda, koristite je na lažnom očekivanju s pozivom na metodu (kao što je prikazano u primjeru u retku).

@Test public void argumentMatching () {UserForm userForm = novi UserForm (); userForm.username = "foo"; // zadani podudarnik EasyMock.expect (loginService.login (EasyMock.isA (UserForm.class))). andReturn (true); // složeno podudaranje loginService.setCurrentUser (specificArgumentMatching ("foo")); EasyMock.replay (loginService); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); EasyMock.verify (loginService); } privatni statički String specificArgumentMatching (očekuje se niz) {EasyMock.reportMatcher (novi IArgumentMatcher () {@Preuzmi javna logička podudaranja (argument objekta) {return argument instance of String && ((String) argument) .startsWith (očekuje se);} @Override public void appendTo (StringBuffer buffer) {// NOOP}}); return null; }

8.3. JMockit

Prilagođeno podudaranje argumenata s JMockitom vrši se pomoću posebnog withArgThat (Matcher) metoda (koja prima Hamcrest-ove Podudaranje predmeti).

@Test public void argumentMatching () {UserForm userForm = novi UserForm (); userForm.username = "foo"; // zadani podudarnik novo Očekivanja () {{loginService.login ((UserForm) bilo koji); rezultat = točno; // složeno podudaranje loginService.setCurrentUser (withArgThat (new BaseMatcher () {@Override javna logička podudaranja (Object item) {return item instanceof String && ((String) item) .startsWith ("foo");} @Override public void descriTo (Opis opisa) {// NOOP}})); }}; Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); nove FullVerifications (loginService) {}; }

9. Djelomično ruganje

9.1. Mockito

Mockito omogućuje djelomično ismijavanje (ismijavanje koje koristi stvarnu implementaciju umjesto ismijanih poziva metode u nekim od svojih metoda) na dva načina.

Možete koristiti .thenCallRealMethod () u uobičajenoj lažnoj definiciji poziva metode ili možete stvoriti špijun umjesto izrugivanja, u tom će slučaju zadano ponašanje biti pozivanje stvarne implementacije u svim ne-izrugivanim metodama.

@Test javna void djelomičnaMocking () {// koristi djelomičnu lažnu prijavuController.loginService = spiedLoginService; UserForm userForm = novi UserForm (); userForm.username = "foo"; // dopustimo da prijava usluge koristi implementaciju, pa se rugajmo DAO pozivu Mockito.when (loginDao.login (userForm)). thenReturn (1); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); // provjera ismijanog poziva Mockito.verify (spiedLoginService) .setCurrentUser ("foo"); }

9.2. EasyMock

Djelomično ruganje također postaje malo komplicirano s EasyMockom, jer trebate definirati koje će se metode rugati prilikom stvaranja lažne slike.

Ovo je učinjeno sa EasyMock.partialMockBuilder (Class.class) .addMockedMethod (“methodName”). CreateMock (). Nakon što to učinite, mozak možete koristiti kao bilo koji drugi ne djelomični lažni ispravak.

@Test javna void djelomičnaMocking () {UserForm userForm = novi UserForm (); userForm.username = "foo"; // koristimo djelomičnu lažnu prijavu LoginService loginServicePartial = EasyMock.partialMockBuilder (LoginService.class) .addMockedMethod ("setCurrentUser"). createMock (); loginServicePartial.setCurrentUser ("foo"); // dopustimo da prijava usluge koristi implementaciju, pa se rugajmo DAO pozivu EasyMock.expect (loginDao.login (userForm)). andReturn (1); loginServicePartial.setLoginDao (loginDao); loginController.loginService = loginServicePartial; EasyMock.replay (loginDao); EasyMock.replay (loginServicePartial); Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); // provjera ismijanog poziva EasyMock.verify (loginServicePartial); EasyMock.verify (loginDao); }

9.3. JMockit

Djelomično ismijavanje s JMockitom posebno je jednostavno. Svaki poziv metode za koji nije definirano ružno ponašanje u Očekivanja () {{}} koristi "stvarna" provedba.

Sad zamislimo da se želimo djelomično rugati LoginService razred za ismijavanje setCurrentUser () metodom dok se koristi stvarna provedba prijaviti se() metoda.

Da bismo to učinili, prvo stvorimo i proslijedimo primjerak LoginService prema bloku očekivanja. Tada bilježimo samo očekivanja za setCurrentUser () metoda:

@Test javna void djelomičnaMocking () {LoginService djelomičnaLoginService = nova LoginService (); djelomičnaLoginService.setLoginDao (loginDao); loginController.loginService = djelomičnaLoginService; UserForm userForm = novi UserForm (); userForm.username = "foo"; nova očekivanja (djelomičnaLoginService) {{// ismijajmo DAO poziv loginDao.login (userForm); rezultat = 1; // nema očekivanja za metodu prijave, tako da se koristi stvarna implementacija // mock setCurrentUser call partLoginService.setCurrentUser ("foo"); }}; Niz login = loginController.login (userForm); Assert.assertEquals ("U redu", prijava); // provjera ismijanog poziva new Verifications () {{djelomičnaLoginService.setCurrentUser ("foo"); }}; }

10. Zaključak

U ovom postu uspoređivali smo tri lažne knjižnice Java, svaka sa svojim jakim stranama i nedostacima.

  • Sva trojica jesu lako se konfigurira s bilješkama koje će vam pomoći u definiranju lažnih i predmeta koji se testiraju, s trkačima kako bi lažno ubrizgavanje bilo što bezbolnije.
    • Rekli bismo da bi Mockito ovdje pobijedio jer ima posebnu napomenu za djelomične lažiranja, ali JMockitu to nije ni potrebno, pa recimo da je to nejednakost između to dvoje.
  • Sva trojica slijede manje-više ono uzorak snimiti-ponoviti-provjeriti, ali prema našem mišljenju, najbolji za to je JMockit jer vas prisiljava da ih koristite u blokovima, tako da testovi postanu strukturiraniji.
  • Lakoća upotrebe je važno kako biste mogli što manje raditi na definiranju testova. JMockit će biti izabrana opcija za svoju fiksnu, uvijek istu strukturu.
  • Mockito je manje-više NAJpoznatiji tako da zajednica bit će veći.
  • Moram nazvati ponoviti svaki put kada želite upotrijebiti lažnu poruku je jasno no-go, tako da ćemo staviti minus jedan za EasyMock.
  • Dosljednost / jednostavnost je također važno za mene. Svidio nam se način vraćanja rezultata JMockita koji je jednak za "normalne" rezultate kao i za iznimke.

Hoće li sve ovo biti rečeno, mi ćemo odabrati JMockit kao svojevrsni pobjednik iako smo ga do sada koristili Mockito jer nas je opčinila jednostavnošću i fiksnom strukturom i od sada ćemo je pokušavati koristiti.

The puna provedba ovog vodiča možete pronaći na projektu GitHub, pa ga slobodno preuzmite i igrajte se s njim.