Mockito vs EasyMock vs JMockit

1. Introduktion

1.1. Oversigt

I dette indlæg skal vi tale om hånende: hvad det er, hvorfor bruge det og flere eksempler på, hvordan man spotter den samme testcase ved hjælp af nogle af de mest anvendte mocking-biblioteker til Java.

Vi starter med nogle formelle / semi-formelle definitioner af spottende begreber; så præsenterer vi sagen under test, følger op med eksempler for hvert bibliotek og ender med nogle konklusioner. De valgte biblioteker er Mockito, EasyMock og JMockit.

Hvis du føler at du allerede kender det grundlæggende ved at spotte, kan du måske springe til punkt 2 uden at læse de næste tre punkter.

1.2. Årsager til at bruge mocks

Vi begynder at antage, at du allerede koder efter nogle drevne udviklingsmetoder, der er centreret om tests (TDD, ATDD eller BDD). Eller bare at du vil oprette en test til en eksisterende klasse, der er afhængig af afhængigheder for at opnå dens funktionalitet.

Under alle omstændigheder, når vi enhedstest en klasse, vil vi test kun dens funktionalitet og ikke dens afhængighed (enten fordi vi stoler på deres implementering eller fordi vi selv tester det).

For at opnå dette er vi nødt til at levere til objektet under test, en erstatning, som vi kan kontrollere for den afhængighed. På denne måde kan vi tvinge ekstreme returværdier, undtagelseskast eller simpelthen reducere tidskrævende metoder til en fast returværdi.

Denne kontrollerede erstatning er spotte, og det hjælper dig med at forenkle testkodning og reducere testudførelsestiden.

1.3. Mock begreber og definition

Lad os se fire definitioner fra en artikel skrevet af Martin Fowler, der opsummerer det grundlæggende, som alle burde vide om mocks:

  • Dummy genstande bliver sendt rundt, men aldrig brugt. Normalt bruges de bare til at udfylde parameterlister.
  • Falske objekter har fungerende implementeringer, men tager normalt en genvej, der gør dem ikke egnede til produktion (en i hukommelsesdatabase er et godt eksempel).
  • Stubbe give dåse svar på opkald foretaget under testen, og svarer normalt slet ikke på noget uden for det, der er programmeret til testen. Stubs registrerer muligvis også oplysninger om opkald, såsom en e-mail-gateway-stub, der husker de meddelelser, den 'sendte', eller måske kun hvor mange meddelelser den 'sendte'.
  • Håner er det, vi taler om her: objekter, der er forprogrammeret med forventninger, der danner en specifikation af de opkald, de forventes at modtage.

1.4 At spotte eller ikke spotte: Det er spørgsmålet

Ikke alt må hånes. Nogle gange er det bedre at lave en integrationstest, da det at spotte den metode / funktion bare ville fungere til lidt faktisk fordel. I vores testtilfælde (som vil blive vist i det næste punkt), ville det teste LoginDao.

Det LoginDao ville bruge et tredjepartsbibliotek til DB-adgang, og spottende ville kun bestå i at sikre, at parametre var forberedt til opkaldet, men vi skulle stadig teste, at opkaldet returnerer de ønskede data.

Af den grund inkluderes det ikke i dette eksempel (selvom vi kunne skrive både enhedstesten med mock-opkald til tredjepartsbiblioteksopkald OG en integrationstest med DBUnit til test af den faktiske ydeevne for tredjepartsbiblioteket).

2. Test sag

Med alt i det foregående afsnit i tankerne, lad os foreslå en ganske typisk testtilfælde, og hvordan vi tester den ved hjælp af mocks (når det giver mening at bruge mocks). Dette vil hjælpe os med at få et fælles scenarie til senere at kunne sammenligne de forskellige spottende biblioteker.

2.1 Forslag til sag

Den foreslåede testsag vil være loginprocessen i en applikation med en lagdelt arkitektur.

Loginanmodningen håndteres af en controller, der bruger en tjeneste, der bruger en DAO (der søger brugerlegitimationsoplysninger på en DB). Vi uddyber ikke for meget i hvert lags implementering og vil fokusere mere på interaktioner mellem komponenterne af hvert lag.

På denne måde får vi en LoginController, a LoginService og en Log indDAO. Lad os se et diagram til afklaring:

2.2 Implementering

Vi følger nu med implementeringen, der er brugt til testsagen, så vi kan forstå, hvad der sker (eller hvad der skal ske) på testene.

Vi starter med den model, der bruges til alle operationer, UserForm, der kun indeholder brugerens navn og adgangskode (vi bruger offentlige adgangsmodifikatorer for at forenkle) og en getter-metode til brugernavn felt for at tillade hån for den egenskab:

offentlig klasse UserForm {offentlig strengadgangskode; offentligt streng brugernavn; public String getUsername () {return username; }}

Lad os følge med Log indDAO, der er ugyldig med funktionalitet, da vi kun vil have dens metoder til at være der, så vi kan spotte dem, når det er nødvendigt:

public class LoginDao {public int login (UserForm userForm) {return 0; }}

LoginDao vil blive brugt af LoginService i dets Log på metode. LoginService vil også have en setCurrentUser metode, der vender tilbage ugyldig for at teste den spottende.

offentlig klasse LoginService {privat LoginDao loginDao; privat streng nuværende bruger; offentlig boolsk login (UserForm userForm) {assert null! = userForm; int loginResults = loginDao.login (userForm); switch (loginResults) {case 1: return true; standard: returner falsk; }} public void setCurrentUser (String username) {if (null! = username) {this.currentUser = username; }}}

Langt om længe, LoginController vil bruge LoginService for dets Log på metode. Dette inkluderer:

  • et tilfælde, hvor der ikke foretages nogen opkald til den hånede tjeneste.
  • et tilfælde, hvor kun en metode kaldes.
  • et tilfælde, hvor alle metoder kaldes.
  • et tilfælde, hvor undtagelseskastning testes.
offentlig klasse LoginController {offentlig LoginService loginService; public String login (UserForm userForm) {if (null == userForm) {return "FEJL"; } andet {boolsk logget; prøv {logget = loginService.login (userForm); } fange (Undtagelse e) {returner "FEJL"; } hvis (logget) {loginService.setCurrentUser (userForm.getUsername ()); returner "OK"; } andet {returner "KO"; }}}}

Nu hvor vi har set, hvad er det, vi prøver at teste, lad os se, hvordan vi håner det med hvert bibliotek.

3. Testopsætning

3.1 Mockito

Til Mockito bruger vi version 2.8.9.

Den nemmeste måde at oprette og bruge mocks på er via @Mock og @InjectMocks kommentarer. Den første opretter en mock til den klasse, der bruges til at definere feltet, og den anden vil forsøge at injicere de oprettede mocks i den kommenterede mock.

Der er flere kommentarer, f.eks @Spion der lader dig oprette en delvis mock (en mock, der bruger den normale implementering i ikke-mocked metoder).

Når det er sagt, skal du ringe MockitoAnnotations.initMocks (dette) inden du udfører nogen test, der vil bruge de nævnte mocks til, at al denne "magi" fungerer. Dette gøres normalt i en @Før kommenteret metode. Du kan også bruge MockitoJUnitRunner.

offentlig klasse LoginControllerTest {@Mock privat LoginDao loginDao; @Spy @InjectMocks privat LoginService spiedLoginService; @Mock privat LoginService loginService; @InjectMocks privat LoginController loginController; @Før offentlig ugyldig setUp () {loginController = ny LoginController (); MockitoAnnotations.initMocks (dette); }}

3.2 EasyMock

Til EasyMock bruger vi version 3.4 (Javadoc). Bemærk, at med EasyMock skal mocks for at begynde at “fungere” ringe EasyMock.replay (mock) på hver testmetode, ellers får du en undtagelse.

Mocks og testede klasser kan også defineres via annoteringer, men i dette tilfælde bruger vi i stedet for at kalde en statisk metode til, at den fungerer. EasyMockRunner til testklassen.

Mocks oprettes med @Mock kommentar og det testede objekt med @TestSubject en (som får dens afhængigheder injiceret fra skabte mocks). Det testede objekt skal oprettes in-line.

@RunWith (EasyMockRunner.class) offentlig klasse LoginControllerTest {@Mock privat LoginDao loginDao; @Mock privat LoginService loginService; @TestSubject privat LoginController loginController = ny LoginController (); }

3.3. JMockit

Til JMockit bruger vi version 1.24 (Javadoc), da version 1.25 endnu ikke er frigivet (i det mindste mens du skriver dette).

Opsætning af JMockit er lige så let som med Mockito, med den undtagelse at der ikke er nogen specifik kommentar til delvise mocks (og faktisk heller ikke noget behov), og at du skal bruge JMockit som testløber.

Mocks defineres ved hjælp af @Injicerbar kommentar (der opretter kun en mock-forekomst) eller med @Drillet annotation (der vil skabe mocks for hver forekomst af klassen i det kommenterede felt).

Den testede forekomst oprettes (og dens spottede afhængigheder injiceres) ved hjælp af @Testet kommentar.

@RunWith (JMockit.class) offentlig klasse LoginControllerTest {@Injicerbar privat LoginDao loginDao; @Injicerbar privat LoginService loginService; @ Testet privat LoginController loginController; }

4. Bekræftelse af ingen opkald til mock

4.1. Mockito

For at kontrollere, at en mock ikke modtog nogen opkald i Mockito, har du metoden verificereZeroInteractions () der accepterer en mock.

@Test offentlig ugyldighed assertThatNoMethodHasBeenCalled () {loginController.login (null); Mockito.verifyZeroInteractions (loginService); }

4.2. EasyMock

For at kontrollere, at en mock ikke modtog nogen opkald, angiver du simpelthen ikke adfærd, du afspiller mocken, og til sidst bekræfter du den.

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

4.3. JMockit

For at kontrollere, at en mock ikke modtog nogen opkald, angiver du simpelthen ikke forventningerne til den mock og foretager en FuldVerifikationer (mock) for nævnte mock.

@Test offentlig ugyldighed assertThatNoMethodHasBeenCalled () {loginController.login (null); nye FullVerifications (loginService) {}; }

5. Definition af Mocked Method-opkald og verificering af opkald til Mocks

5.1. Mockito

Til spottemetode opkald, du kan bruge Mockito.when (mock.method (args)). DerefterReturn (værdi). Her kan du returnere forskellige værdier for mere end et opkald ved blot at tilføje dem som flere parametre: thenReturn (værdi1, værdi2, værdi-n,…).

Bemærk, at du ikke kan spotte ugyldige returneringsmetoder med denne syntaks. I nævnte tilfælde bruger du en verifikation af metoden (som vist på linje 11).

Til bekræftelse af opkald til en mock du kan bruge Mockito.verify (mock) .metode (args) og du kan også kontrollere, at der ikke blev foretaget flere opkald til en mock ved hjælp af verificereNoMoreInteractions (mock).

Til bekræftende args, kan du videregive bestemte værdier eller bruge foruddefinerede matchere som nogen(), anyString (), anyInt (). Der er meget mere af den slags matchere og endda muligheden for at definere dine matchere, som vi vil se i de følgende eksempler.

@Test offentlig ugyldighed assertTwoMethodsHaveBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; Mockito.when (loginService.login (userForm)). DerefterReturn (true); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); Mockito.verify (loginService) .login (userForm); Mockito.verify (loginService) .setCurrentUser ("foo"); } @Test offentlig ugyldighed assertOnlyOneMethodHasBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; Mockito.when (loginService.login (userForm)). DerefterReturn (false); String login = loginController.login (userForm); Assert.assertEquals ("KO", login); Mockito.verify (loginService) .login (userForm); Mockito.verifyNoMoreInteractions (loginService); }

5.2. EasyMock

Til spottemetode opkald, du bruger EasyMock.expect (mock.method (args)). Og Retur (værdi).

Til bekræftelse af opkald til en hån, kan du bruge EasyMock.verify (mock), men du skal kalde det altid efter ringer EasyMock.replay (mock).

Til bekræftende args, kan du videregive bestemte værdier, eller du har foruddefinerede matchere som isA(Klasse klasse), anyString (), anyInt (), og meget mere af den slags matchere og igen muligheden for at definere dine matchere.

@Test offentlig ugyldighed assertTwoMethodsHaveBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; EasyMock.expect (loginService.login (userForm)). OgReturn (true); loginService.setCurrentUser ("foo"); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); EasyMock.verify (loginService); } @Test offentlig ugyldighed assertOnlyOneMethodHasBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; EasyMock.expect (loginService.login (userForm)). OgReturn (false); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("KO", login); EasyMock.verify (loginService); }

5.3. JMockit

Med JMockit har du defineret trin til test: optag, afspil og bekræft.

Optage gøres i en ny Forventninger () {{}} blok (hvor du kan definere handlinger for flere mocks), afspilning gøres simpelthen ved at påkalde en metode i den testede klasse (der skal kalde et spottet objekt), og verifikation gøres inde i en ny Bekræftelser () {{}} blok (hvor du kan definere verifikationer for flere mocks).

Til spottemetode opkald, du kan bruge mock. metode (args); resultat = værdi; inde i enhver Forventninger blok. Her kan du returnere forskellige værdier for mere end et opkald ved bare at bruge returnerer (værdi1, værdi2,…, værdi); i stedet for resultat = værdi;.

Til bekræftelse af opkald til en mock kan du bruge nye verifikationer() {{mock.call (værdi)}} eller nye verifikationer (mock) {{}} for at bekræfte alle tidligere definerede forventede opkald.

Til bekræftende args, kan du videregive bestemte værdier, eller du har foruddefinerede værdier som f.eks nogen, anyString, anyLong, og meget mere af den slags specielle værdier og igen muligheden for at definere dine matchere (det skal være Hamcrest-matchere).

@Test offentlig ugyldighed assertTwoMethodsHaveBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; nye forventninger () {{loginService.login (userForm); resultat = sandt; loginService.setCurrentUser ("foo"); }}; String login = loginController.login (userForm); Assert.assertEquals ("OK", login); nye FullVerifications (loginService) {}; } @Test offentlig ugyldighed assertOnlyOneMethodHasBeenCalled () {UserForm userForm = ny UserForm (); userForm.username = "foo"; nye forventninger () {{loginService.login (userForm); resultat = falsk; // ingen forventning til setCurrentUser}}; String login = loginController.login (userForm); Assert.assertEquals ("KO", login); nye FullVerifications (loginService) {}; }

6. Spottende undtagelseskastning

6.1. Mockito

Undtagelseskast kan bespottes ved hjælp af .thenThrow (ExceptionClass.class) efter en Mockito.when (mock.method (args)).

@Test offentlig ugyldig mockExceptionThrowin () {UserForm userForm = ny UserForm (); Mockito.when (loginService.login (userForm)). Derefter Kast (IllegalArgumentException.class); String login = loginController.login (userForm); Assert.assertEquals ("FEJL", login); Mockito.verify (loginService) .login (userForm); Mockito.verifyZeroInteractions (loginService); }

6.2. EasyMock

Undtagelseskast kan bespottes ved hjælp af .andThrow (ny ExceptionClass ()) efter en EasyMock.expect (…) opkald.

@Test offentlig ugyldig mockExceptionThrowing () {UserForm userForm = ny UserForm (); EasyMock.expect (loginService.login (userForm)). Og Kast (nyt IllegalArgumentException ()); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("FEJL", login); EasyMock.verify (loginService); }

6.3. JMockit

Spottende undtagelse at kaste med JMockito er især let. Du skal bare returnere en undtagelse som et resultat af et hånet metodeopkald i stedet for det “normale” retur.

@Test offentlig ugyldig mockExceptionThrowing () {UserForm userForm = ny UserForm (); nye forventninger () {{loginService.login (userForm); resultat = nyt IllegalArgumentException (); // ingen forventning til setCurrentUser}}; String login = loginController.login (userForm); Assert.assertEquals ("FEJL", login); nye FullVerifications (loginService) {}; }

7. Spotte et objekt, der skal passeres rundt

7.1. Mockito

Du kan oprette en mock, der også skal overføres som et argument for et metodekald. Med Mockito kan du gøre det med en en-liner.

@Test offentlig ugyldig mockAnObjectToPassAround () {UserForm userForm = Mockito.when (Mockito.mock (UserForm.class) .getUsername ()) .thenReturn ("foo"). GetMock (); Mockito.when (loginService.login (userForm)). DerefterReturn (true); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); Mockito.verify (loginService) .login (userForm); Mockito.verify (loginService) .setCurrentUser ("foo"); }

7.2. EasyMock

Mocks kan oprettes på linje med EasyMock.mock (klasse.klasse). Bagefter kan du bruge EasyMock.expect (mock.method ()) at forberede det til udførelse, altid huske at ringe EasyMock.replay (mock) inden brug.

@Test offentlig ugyldig mockAnObjectToPassAround () {UserForm userForm = EasyMock.mock (UserForm.class); EasyMock.expect (userForm.getUsername ()). OgReturn ("foo"); EasyMock.expect (loginService.login (userForm)). OgReturn (true); loginService.setCurrentUser ("foo"); EasyMock.replay (userForm); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); EasyMock.verify (userForm); EasyMock.verify (loginService); }

7.3. JMockit

For at spotte et objekt til kun en metode kan du blot sende det spottet som en parameter til testmetoden. Derefter kan du skabe forventninger som med enhver anden mock.

@Test offentlig ugyldig mockAnObjectToPassAround (@Mocked UserForm userForm) {new Expectations () {{userForm.getUsername (); resultat = "foo"; loginService.login (userForm); resultat = sandt; loginService.setCurrentUser ("foo"); }}; String login = loginController.login (userForm); Assert.assertEquals ("OK", login); nye FullVerifications (loginService) {}; nye FullVerifikationer (userForm) {}; }

8. Tilpasning af brugerdefineret argument

8.1. Mockito

Nogle gange skal argumentmatchning for mocked opkald være lidt mere kompleks end blot en fast værdi eller anyString (). I de tilfælde har Mockito sin matcherklasse, der bruges med argThat (ArgumentMatcher).

@Test offentligt ugyldigt argumentMatching () {UserForm userForm = ny UserForm (); userForm.username = "foo"; // standard matcher Mockito.when (loginService.login (Mockito.any (UserForm.class))). derefterReturn (sand); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); Mockito.verify (loginService) .login (userForm); // kompleks matcher Mockito.verify (loginService) .setCurrentUser (ArgumentMatchers.argThat (ny ArgumentMatcher () {@Override offentlige boolske matches (String argument) {return argument.startsWith ("foo");}})); }

8.2. EasyMock

Tilpasning af tilpasset argument er lidt mere kompliceret med EasyMock, da du skal oprette en statisk metode, hvor du opretter den aktuelle matcher og derefter rapporterer den med EasyMock.reportMatcher (IArgumentMatcher).

Når denne metode er oprettet, bruger du den på din håne forventning med et opkald til metoden (som det ses i eksemplet i linjen).

@Test offentligt ugyldigt argumentMatching () {UserForm userForm = ny UserForm (); userForm.username = "foo"; // standard matcher EasyMock.expect (loginService.login (EasyMock.isA (UserForm.class))). og Retur (sand); // kompleks matcher loginService.setCurrentUser (specificArgumentMatching ("foo")); EasyMock.replay (loginService); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); EasyMock.verify (loginService); } privat statisk streng specificArgumentMatching (streng forventet) {EasyMock.reportMatcher (ny IArgumentMatcher () {@ Override offentlige boolske matches (Objektargument) {return argument instanceof String && ((String) argument)) starter med (forventet);} @ Overstyr offentlig ugyldig appendTo (StringBuffer-buffer) {// NOOP}}); returnere null; }

8.3. JMockit

Tilpasning af tilpasset argument med JMockit udføres med specialet withArgThat (Matcher) metode (der modtager Hamcrest Matcher genstande).

@Test offentligt ugyldigt argumentMatching () {UserForm userForm = ny UserForm (); userForm.username = "foo"; // standard matcher nye Expectations () {{loginService.login ((UserForm) any); resultat = sandt; // complex matcher loginService.setCurrentUser (withArgThat (new BaseMatcher () {@Override public boolean matches (Object item) {return item instance of String && ((String) item) .startsWith ("foo");} @ Overstyr offentlig ugyldig beskrivelse til) (Beskrivelse af beskrivelse) {// NOOP}})); }}; String login = loginController.login (userForm); Assert.assertEquals ("OK", login); nye FullVerifications (loginService) {}; }

9. Delvis hån

9.1. Mockito

Mockito tillader delvis mocking (en mock, der bruger den virkelige implementering i stedet for mocked metode, kalder på nogle af dens metoder) på to måder.

Du kan enten bruge .thenCallRealMethod () i en normal mock-metode kald definition, eller du kan oprette en spion i stedet for en mock, i hvilket tilfælde standardadfærden for det er at kalde den virkelige implementering i alle ikke-mocked metoder.

@Test offentlig ugyldig partialMocking () {// brug delvis mock loginController.loginService = spiedLoginService; UserForm userForm = ny UserForm (); userForm.username = "foo"; // lad servicens login bruge implementering, så lad os spotte DAO-opkald til Mockito.when (loginDao.login (userForm)). thenReturn (1); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); // verificer spottet opkald Mockito.verify (spiedLoginService) .setCurrentUser ("foo"); }

9.2. EasyMock

Delvis mocking bliver også lidt mere kompliceret med EasyMock, da du skal definere, hvilke metoder der skal bespottes, når du opretter mocken.

Dette gøres med EasyMock.partialMockBuilder (Class.class) .addMockedMethod (“methodName”). CreateMock (). Når dette er gjort, kan du bruge mocken som enhver anden ikke-delvis mock.

@Test offentlig ugyldig partialMocking () {UserForm userForm = ny UserForm (); userForm.username = "foo"; // brug delvis mock LoginService loginServicePartial = EasyMock.partialMockBuilder (LoginService.class) .addMockedMethod ("setCurrentUser"). createMock (); loginServicePartial.setCurrentUser ("foo"); // lad servicens login bruge implementering, så lad os spotte DAO-kaldet EasyMock.expect (loginDao.login (userForm)). andReturn (1); loginServicePartial.setLoginDao (loginDao); loginController.loginService = loginServicePartial; EasyMock.replay (loginDao); EasyMock.replay (loginServicePartial); String login = loginController.login (userForm); Assert.assertEquals ("OK", login); // verificer spottet opkald EasyMock.verify (loginServicePartial); EasyMock.verify (loginDao); }

9.3. JMockit

Delvis hån med JMockit er særlig let. Hver metodeopkald, for hvilken der ikke er defineret spottet adfærd i en Forventninger () {{}} anvendelser den “rigtige” implementering.

Lad os forestille os, at vi delvist vil spotte LoginService klasse at spotte setCurrentUser () metode, mens du bruger den faktiske implementering af Log på() metode.

For at gøre dette opretter og videregiver vi først en forekomst af LoginService til forventningsblokken. Derefter registrerer vi kun en forventning til setCurrentUser () metode:

@Test offentlig ugyldig partialMocking () {LoginService partialLoginService = ny LoginService (); partialLoginService.setLoginDao (loginDao); loginController.loginService = partialLoginService; UserForm userForm = ny UserForm (); userForm.username = "foo"; nye forventninger (partialLoginService) {{// lad os spotte DAO-opkald loginDao.login (userForm); resultat = 1; // ingen forventning om login-metode, så der anvendes ægte implementering // mock setCurrentUser-opkald partialLoginService.setCurrentUser ("foo"); }}; String login = loginController.login (userForm); Assert.assertEquals ("OK", login); // verificer mocked call new Verifications () {{partialLoginService.setCurrentUser ("foo"); }}; }

10. Konklusion

I dette indlæg har vi sammenlignet tre Java-mock-biblioteker, hver med sine stærke sider og ulemper.

  • De er alle tre let konfigureret med kommentarer til at hjælpe dig med at definere mocks og objektet under test, med løbere for at gøre mockinjektion så smertefri som muligt.
    • Vi vil sige, at Mockito ville vinde her, da den har en særlig kommentar til delvise mocks, men JMockit har ikke engang brug for det, så lad os sige, at det er uafgjort mellem disse to.
  • Alle tre følger dem mere eller mindre optag-gentag-bekræft mønster, men efter vores mening er den bedste til at gøre det JMockit, da det tvinger dig til at bruge dem i blokke, så testene bliver mere strukturerede.
  • Lethed brug er vigtig, så du kan arbejde så mindre som muligt for at definere dine tests. JMockit vil være den valgte mulighed for sin faste-altid-samme struktur.
  • Mockito er mere eller mindre DEN mest kendte, således at fællesskab bliver større.
  • At skulle ringe afspilning hver gang du vil bruge en mock er en klar Nej, så vi sætter et minus til EasyMock.
  • Konsistens / enkelhed er også vigtigt for mig. Vi elskede måden at returnere resultater af JMockit, der er den samme for "normale" resultater som for undtagelser.

Vil alt dette blive sagt, skal vi vælge JMockit som en slags vinder, selvom vi indtil nu har brugt Mockito som vi er blevet betaget af sin enkelhed og faste struktur og vil prøve at bruge det fra nu af.

Det fuld implementering af denne vejledning kan findes på GitHub-projektet, så er du velkommen til at downloade den og lege med den.