Uvod u EasyMock
1. Uvod
U prošlosti smo opširno razgovarali o JMockitu i Mockitu.
U ovom uputstvu dat ćemo uvod u drugi alat za ruganje - EasyMock.
2. Ovisnosti Mavena
Prije nego što zaronimo, dodajmo sljedeću ovisnost našoj pom.xml:
org.easymock easymock 3.5.1 test
Najnoviju verziju uvijek možete pronaći ovdje.
3. Temeljni koncepti
Kada generirate lažni možemo simulirati ciljni objekt, odrediti njegovo ponašanje i na kraju provjeriti koristi li se prema očekivanjima.
Rad s motivima EasyMocka uključuje četiri koraka:
- stvaranje makete ciljne klase
- bilježenje očekivanog ponašanja, uključujući radnju, rezultat, iznimke itd.
- koristeći lažne testove
- provjeravanje ponaša li se očekivano
Nakon što naše snimanje završi, prebacimo ga u način "ponovnog reprodukcije", tako da se maketa ponaša kao snimljena tijekom suradnje s bilo kojim objektom koji će je koristiti.
Na kraju provjeravamo ide li sve prema očekivanjima.
Četiri gore navedena koraka odnose se na metode u org.easymock.EasyMock:
- oponašanje(…): generira lažni prikaz ciljne klase, bila to konkretna klasa ili sučelje. Jednom stvoren, maketa je u načinu snimanja, što znači da će EasyMock snimiti sve radnje koje izvrši Mock Object i reproducirati ih u načinu "replay"
- očekivati(…): ovom metodom možemo postaviti očekivanja, uključujući pozive, rezultate i iznimke, za povezane radnje snimanja
- ponoviti (…): prebacuje zadani lažni prikaz u način "ponovnog reprodukcije". Zatim će svaka radnja koja pokreće prethodno snimljene pozive metode ponoviti "snimljene rezultate"
- potvrditi (...): potvrđuje da su ispunjena sva očekivanja i da nije izveden neočekivani poziv lažno
U sljedećem odjeljku pokazat ćemo kako ovi koraci djeluju na primjeru iz stvarnog svijeta.
4. Praktični primjer ruganja
Prije nego što nastavimo, pogledajmo primjer primjera: recimo da imamo čitatelja bloga Baeldung koji voli pregledavati članke na web mjestu, a zatim pokušava napisati članke.
Počnimo sa stvaranjem sljedećeg modela:
javna klasa BaeldungReader {private ArticleReader articleReader; private IArticleWriter articleWriter; // konstruktori public BaeldungArticle readNext () {return articleReader.next (); } javni popis readTopic (tema niza) {return articleReader.ofTopic (tema); } javni zapis niza (naslov niza, sadržaj niza) {return articleWriter.write (naslov, sadržaj); }}
U ovom modelu imamo dva privatna člana: articleReader(konkretna klasa) i articleWriter (sučelje).
Dalje ćemo im se rugati kako bismo provjerili BaeldungReader'S ponašanje.
5. Rugajte se Java kodu
Počnimo s ismijavanjem ArticleReader.
5.1. Tipično ruganje
Očekujemo articleReader.next () metoda koja se poziva kada čitatelj preskoči članak:
@Test public void whenReadNext_thenNextArticleRead () {ArticleReader mockArticleReader = lažno (ArticleReader.class); BaeldungReader baeldungReader = novi BaeldungReader (mockArticleReader); očekivati (mockArticleReader.next ()). andReturn (null); ponoviti (mockArticleReader); baeldungReader.readNext (); provjeriti (mockArticleReader); }
U gornjem uzorku koda strogo se pridržavamo postupka u 4 koraka i ismijavamo ArticleReader razred.
Iako nas stvarno nije briga što mockArticleReader.next () vraća, još trebamo navesti povratnu vrijednost za mockArticleReader.next () pomoću očekujte (...). i vratite se (...).
S očekivati(…), EasyMock očekuje da metoda vrati vrijednost ili baci znak Iznimka.
Ako to jednostavno učinimo:
mockArticleReader.next (); ponoviti (mockArticleReader);
EasyMock će se žaliti na ovo, jer zahtijeva poziv očekujte (...). i vratite se (...) ako metoda nešto vrati.
Ako je a poništiti metodom, možemo očekivati njegovo djelovanje pomoću awactLastCall () kao ovo:
mockArticleReader.someVoidMethod (); awactLastCall (); ponoviti (mockArticleReader);
5.2. Ponovite redoslijed
Ako trebamo ponoviti radnje u određenom redoslijedu, možemo biti stroži:
@Test public void whenReadNextAndSkimTopics_thenAllAllowed () {ArticleReader mockArticleReader = strictMock (ArticleReader.class); BaeldungReade baeldungReader = novi BaeldungReader (mockArticleReader); očekivati (mockArticleReader.next ()). andReturn (null); očekujte (mockArticleReader.ofTopic ("easymock")). andReturn (null); ponoviti (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); provjeriti (mockArticleReader); }
U ovom isječku mi koristiti StrogiMock (...) za provjeru redoslijeda poziva metode. Za podsmijehe koje je stvorio oponašanje(…) i StrogiMock (...), svaki neočekivani poziv metode uzrokovao bi AssertionError.
Možemo upotrijebiti bilo koji metodski poziv za lažnu sliku niceMock (...):
@Test public void whenReadNextAndOthers_thenAllowed () {ArticleReader mockArticleReader = niceMock (ArticleReader.class); BaeldungReade baeldungReader = novi BaeldungReader (mockArticleReader); očekivati (mockArticleReader.next ()). andReturn (null); ponoviti (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); provjeriti (mockArticleReader); }
Ovdje nismo očekivali baeldungReader.readTopic (...) biti pozvan, ali EasyMock se neće žaliti. S niceMock (…), EasyMock sada brine samo je li ciljni objekt izvršio očekivanu radnju ili nije.
5.3. Ruganje Iznimka Baca
Sada, nastavimo s ismijavanjem sučelja IArticleWriter, i kako postupati s očekivanim Bacači:
@Test public void whenWriteMaliciousContent_thenArgumentIllegal () {// očekuje se ruganje i inicijalizacija (mockArticleWriter .write ("easymock", "")) .andThrow (new IllegalArgumentException ()); ponoviti (mockArticleWriter); // zapisivanje zlonamjernog sadržaja i hvatanje iznimke prema očekivanjuException provjere (mockArticleWriter); assertEquals (IllegalArgumentException.class, očekujeException.getClass ()); }
U gornjem isječku očekujemo articleWriter je dovoljno čvrst da otkrije XSS (Cross-site Scripting) napade.
Dakle, kada čitatelj pokuša ubaciti zlonamjerni kod u sadržaj članka, pisac bi trebao baciti znak IlegalArgumentException. Ovo očekivano ponašanje zabilježili smo koristeći očekujte (...). i baci (...).
6. Rugaj se s bilješkama
EasyMock također podržava ubrizgavanje lažnih slika pomoću bilješki. Da bismo ih koristili, moramo pokrenuti naše jedinične testove s EasyMockRunner tako da obrađuje @Oponašanje i @TestSubject bilješke.
Prepišimo prethodne isječke:
@RunWith (EasyMockRunner.class) javna klasa BaeldungReaderAnnotatedTest {@Mock ArticleReader mockArticleReader; @TestSubject BaeldungReader baeldungReader = novi BaeldungReader (); @Test public void whenReadNext_thenNextArticleRead () {očekivati (mockArticleReader.next ()). AndReturn (null); ponoviti (mockArticleReader); baeldungReader.readNext (); provjeriti (mockArticleReader); }}
Ekvivalentno oponašanje(…), mock će se ubrizgati u polja označena s @Oponašanje. I ove će se lažne slike ubrizgati u polja klase označene s @TestSubject.
U gornjem isječku nismo eksplicitno inicijalizirali articleReader polje u baeldungReader. Pri pozivu baeldungReader.readNext (), to možemo implicitno nazvati mockArticleReader.
To je bilo zato mockArticleReader je ubrizgano u članakReader polje.
Imajte na umu da ako želimo koristiti drugi test trkač umjesto EasyMockRunner, možemo koristiti pravilo JUnit testa EasyMockRule:
javna klasa BaeldungReaderAnnotatedWithRuleTest {@Rule javno EasyMockRule mockRule = novo EasyMockRule (ovo); // ... @Test public void whenReadNext_thenNextArticleRead () {očekivati (mockArticleReader.next ()). AndReturn (null); ponoviti (mockArticleReader); baeldungReader.readNext (); provjeriti (mockArticleReader); }}
7. Rugajte se EasyMockSupport
Ponekad u jedan test moramo uvesti više ismijavanja, a moramo ručno ponoviti:
ponavljanje (A); ponavljanje (B); ponavljanje (C); // ... provjeriti (A); provjeriti (B); provjeriti (C);
Ovo je ružno i trebamo elegantno rješenje.
Srećom, imamo nastavu EasyMockSupport u EasyMocku da pomogne u rješavanju ovoga. To pomaže u praćenju ismijavanja, tako da ih možemo ponovno reproducirati i provjeriti serija poput ove:
// ... javna klasa BaeldungReaderMockSupportTest proširuje EasyMockSupport {// ... @Test javna praznina kadaReadAndWriteSequenically_thenWorks () {očekivati (mockArticleReader.next ()). ; očekivati (mockArticleWriter.write ("naslov", "sadržaj")) .andReturn ("BAEL-201801"); replayAll (); // izvršavamo operacije čitanja i pisanja uzastopno verifyAll (); assertEquals (NoSuchElementException.class, očekujeException.getClass ()); assertEquals ("BAEL-201801", articleId); }}
Ovdje smo se rugali oboma articleReader i articleWriter. Prilikom postavljanja ovih lažnih slika u način "ponovne reprodukcije", koristili smo statičku metodu replayAll () koje pruža EasyMockSupport, i koristi se verifyAll () kako bi provjerili njihovo ponašanje u serijama.
Također smo predstavili puta (…) metoda u očekivati faza. Pomaže u određivanju koliko puta očekujemo da se metoda pozove kako bismo izbjegli uvođenje dupliciranog koda.
Možemo i koristiti EasyMockSupport putem delegiranja:
EasyMockSupport easyMockSupport = novi EasyMockSupport (); @Test public void whenReadAndWriteSequenically_thenWorks () {ArticleReader mockArticleReader = easyMockSupport .createMock (ArticleReader.class); IArticleWriter mockArticleWriter = easyMockSupport .createMock (IArticleWriter.class); BaeldungReader baeldungReader = novi BaeldungReader (mockArticleReader, mockArticleWriter); očekivati (mockArticleReader.next ()). andReturn (null); očekujte (mockArticleWriter.write ("naslov", "sadržaj")) .andReturn (""); easyMockSupport.replayAll (); baeldungReader.readNext (); baeldungReader.write ("naslov", "sadržaj"); easyMockSupport.verifyAll (); }
Prije smo koristili statičke metode ili napomene za stvaranje i upravljanje mockovima. Ispod poklopca motora ovim statičkim i anotiranim podsmjehom upravlja global EasyMockSupport primjer.
Ovdje smo to izričito izradili i uzeli smo sve te podsmjehe pod svoju kontrolu, putem delegiranja. To može pomoći u izbjegavanju zabune ako u našem testnom kodu s EasyMockom postoje sukobi imena ili u sličnim slučajevima.
8. Zaključak
U ovom smo članku ukratko predstavili osnovnu upotrebu EasyMocka o tome kako generirati lažne objekte, snimiti i ponoviti njihovo ponašanje te provjeriti jesu li se ponašali ispravno.
U slučaju da biste mogli biti zainteresirani, pogledajte ovaj članak za usporedbu EasyMock-a, Mocket-a i JMockita.
Kao i uvijek, cjelovitu implementaciju možete pronaći na Githubu.