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:

  1. stvaranje makete ciljne klase
  2. bilježenje očekivanog ponašanja, uključujući radnju, rezultat, iznimke itd.
  3. koristeći lažne testove
  4. 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:

  1. 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"
  2. očekivati(…): ovom metodom možemo postaviti očekivanja, uključujući pozive, rezultate i iznimke, za povezane radnje snimanja
  3. 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"
  4. 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.