Introduksjon til EasyMock

1. Introduksjon

Tidligere har vi snakket mye om JMockit og Mockito.

I denne opplæringen vil vi gi en introduksjon til et annet mocking-verktøy - EasyMock.

2. Maven-avhengigheter

Før vi dykker inn, la oss legge til følgende avhengighet til vår pom.xml:

 org.easymock easymock 3.5.1 test 

Den siste versjonen finner du alltid her.

3. Kjernekonsepter

Når du genererer en hån, vi kan simulere målobjektet, spesifisere oppførselen og til slutt verifisere om det brukes som forventet.

Arbeid med EasyMocks mocks innebærer fire trinn:

  1. skape en narr av målklassen
  2. registrerer forventet oppførsel, inkludert handling, resultat, unntak osv.
  3. bruke mocks i tester
  4. verifisere om den oppfører seg som forventet

Etter at opptaket er ferdig, bytter vi det til “replay” -modus, slik at mocken oppfører seg som registrert når du samarbeider med et hvilket som helst objekt som skal bruke den.

Til slutt verifiserer vi om alt går som forventet.

De fire trinnene som er nevnt ovenfor, gjelder metoder i org.easymock.EasyMock:

  1. håne(…): genererer en narr av målklassen, det være seg en konkret klasse eller et grensesnitt. Når den er opprettet, er en mock i “opptaksmodus”, noe som betyr at EasyMock vil registrere enhver handling Mock Object tar, og spille dem på nytt i “replay” -modus.
  2. forvent (...): med denne metoden kan vi stille forventninger, inkludert samtaler, resultater og unntak, for tilknyttede opptakshandlinger
  3. avspilling (...): bytter en gitt mock til “replay” -modus. Deretter vil enhver handling som utløser tidligere innspilte metodesamtaler spille av “innspilte resultater” på nytt
  4. bekrefte(…): bekrefter at alle forventninger ble oppfylt og at ingen uventede samtaler ble utført på en hån

I neste avsnitt viser vi hvordan disse trinnene fungerer i praksis, ved hjelp av eksempler fra den virkelige verden.

4. Et praktisk eksempel på spott

Før vi fortsetter, la oss se på eksemplet på konteksten: si at vi har en leser av Baeldung-bloggen, som liker å bla gjennom artikler på nettstedet, og deretter prøver han / hun å skrive artikler.

La oss starte med å lage følgende modell:

public class BaeldungReader {private ArticleReader articleReader; privat IArticleWriter artikkelWriter; // offentlige konstruktører BaeldungArticle readNext () {return articleReader.next (); } offentlig liste readTopic (strengemne) {return articleReader.ofTopic (topic); } public String write (String title, String content) {return articleWriter.write (title, content); }}

I denne modellen har vi to private medlemmer: ArticleReader(en konkret klasse) og ArticleWriter (et grensesnitt).

Deretter håner vi dem for å bekrefte BaeldungReader’Oppførsel.

5. Hån med Java-kode

La oss begynne med å spotte en ArticleReader.

5.1. Typisk hån

Vi forventer at articleReader.next () metode som skal kalles når en leser hopper over en artikkel:

@Test offentlig ugyldig nårReadNext_thenNextArticleRead () {ArticleReader mockArticleReader = mock (ArticleReader.class); BaeldungReader baeldungReader = ny BaeldungReader (mockArticleReader); forvent (mockArticleReader.next ()). ogReturn (null); reprise (mockArticleReader); baeldungReader.readNext (); verifisere (mockArticleReader); }

I eksempelkoden ovenfor holder vi oss strengt til 4-trinns prosedyren og håner ArticleReader klasse.

Selv om vi ikke bryr oss hva mockArticleReader.next () returnerer, må vi fremdeles spesifisere en returverdi for mockArticleReader.next () ved bruk av forvent (...) .og Retur (...).

Med forvent (...), EasyMock forventer at metoden skal returnere en verdi eller kaste en Unntak.

Hvis vi bare gjør det:

mockArticleReader.next (); reprise (mockArticleReader);

EasyMock vil klage på dette, da det krever en samtale forvent (…) .og Retur (…) hvis metoden returnerer noe.

Hvis det er en tomrom metoden, kan vi forventer sin handling ved hjelp av expectLastCall () som dette:

mockArticleReader.someVoidMethod (); expectLastCall (); reprise (mockArticleReader);

5.2. Replay Order

Hvis vi trenger at handlinger skal spilles på nytt i en bestemt rekkefølge, kan vi være strengere:

@Test offentlig ugyldig nårReadNextAndSkimTopics_thenAllAllowed () {ArticleReader mockArticleReader = strictMock (ArticleReader.class); BaeldungReade baeldungReader = ny BaeldungReader (mockArticleReader); forvent (mockArticleReader.next ()). ogReturn (null); expect (mockArticleReader.ofTopic ("easymock")). ogReturn (null); reprise (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); verifisere (mockArticleReader); }

I dette utdraget, vi bruk strictMock (…) for å sjekke rekkefølgen på metodeanrop. For hån skapt av håne(…) og strictMock (…), vil eventuelle uventede metodesamtaler føre til en Påstand Feil.

For å tillate en hvilken som helst metodekall for spotten, kan vi bruke niceMock (…):

@Test offentlig ugyldig nårReadNextAndOthers_thenAllowed () {ArticleReader mockArticleReader = niceMock (ArticleReader.class); BaeldungReade baeldungReader = ny BaeldungReader (mockArticleReader); forvent (mockArticleReader.next ()). ogReturn (null); reprise (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); verifisere (mockArticleReader); }

Her forventet vi ikke baeldungReader.readTopic (…) å bli kalt, men EasyMock vil ikke klage. Med niceMock (…), EasyMock bryr seg nå bare om målobjektet utførte forventet handling eller ikke.

5.3. Gjøre narr av Unntak Kaster

La oss nå fortsette med å spotte grensesnittet IArticleWriter, og hvordan håndtere forventet Kastevarer:

@Test offentlig ugyldig nårWriteMaliciousContent_thenArgumentIllegal () {// hån og initialisering forventer (mockArticleWriter .write ("easymock", "")). OgTrow (ny IllegalArgumentException ()); reprise (mockArticleWriter); // skrive skadelig innhold og fange unntak som forventetException verifisere (mockArticleWriter); assertEquals (IllegalArgumentException.class, expectException.getClass ()); }

I utdraget over forventer vi at ArticleWriter er solid nok til å oppdage XSS (Cross-site Scripting) -angrep.

Så når leseren prøver å injisere skadelig kode i artikkelinnholdet, bør forfatteren kaste en IllegalArgumentException. Vi registrerte denne forventede atferden ved hjelp av forvent (...). og kast (...).

6. Hån med kommentar

EasyMock støtter også injisering av mocks ved hjelp av merknader. For å bruke dem, må vi kjøre enhetstestene våre med EasyMockRunner slik at det prosesser @Håne og @Prøvekanin kommentarer.

La oss skrive om tidligere utdrag:

@RunWith (EasyMockRunner.class) offentlig klasse BaeldungReaderAnnotatedTest {@Mock ArticleReader mockArticleReader; @TestSubject BaeldungReader baeldungReader = ny BaeldungReader (); @Test offentlig ugyldig nårReadNext_thenNextArticleRead () {expect (mockArticleReader.next ()). AndReturn (null); reprise (mockArticleReader); baeldungReader.readNext (); verifisere (mockArticleReader); }}

Tilsvarende håne(…), vil en mock bli injisert i felt merket med @Håne. Og disse hånene vil bli injisert i felt i klassen som er merket med @Prøvekanin.

I kodebiten ovenfor initialiserte vi ikke eksplisitt ArticleReader felt i baeldungReader. Når du ringer baeldungReader.readNext (), kan vi interforere som implisitt kalt mockArticleReader.

Det var fordi mockArticleReader ble injisert til artikkelenLeser felt.

Merk at hvis vi vil bruke en annen testløper i stedet for EasyMockRunner, kan vi bruke JUnit-testregelen EasyMockRule:

offentlig klasse BaeldungReaderAnnotatedWithRuleTest {@Rule offentlig EasyMockRule mockRule = ny EasyMockRule (dette); // ... @Test public void whenReadNext_thenNextArticleRead () {expect (mockArticleReader.next ()). AndReturn (null); reprise (mockArticleReader); baeldungReader.readNext (); verifisere (mockArticleReader); }}

7. Hån med EasyMockSupport

Noen ganger trenger vi å introdusere flere mocks i en enkelt test, og vi må gjenta manuelt:

reprise (A); reprise (B); reprise (C); // ... verifisere (A); verifisere (B); verifisere (C);

Dette er stygt, og vi trenger en elegant løsning.

Heldigvis har vi en klasse EasyMockSupport i EasyMock for å hjelpe til med å takle dette. Den hjelper med å holde rede på hån, slik at vi kan spille av og bekrefte dem på nytt et parti som dette:

// ... offentlig klasse BaeldungReaderMockSupportTest utvider EasyMockSupport {// ... @Test offentlig ugyldig nårReadAndWriteSequencially_thenWorks () {expect (mockArticleReader.next ()). andReturn (null) .times (2) .andThrow (new NoSuchElementException ; forvent (mockArticleWriter.write ("title", "content")). og Retur ("BAEL-201801"); replayAll (); // utføre lese- og skriveoperasjoner fortløpende verifisereAll (); assertEquals (NoSuchElementException.class, expectException.getClass ()); assertEquals ("BAEL-201801", ArticleId); }}

Her spottet vi begge deler ArticleReader og ArticleWriter. Når vi satte disse mockene til “replay” -modus, brukte vi en statisk metode replayAll () levert av EasyMockSupport, og brukt verifisereAlle () for å verifisere deres oppførsel i batch.

Vi introduserte også ganger (…) metoden i forventer fase. Det hjelper med å spesifisere hvor mange ganger vi forventer at metoden skal kalles, slik at vi kan unngå å innføre duplikatkode.

Vi kan også bruke EasyMockSupport gjennom delegering:

EasyMockSupport easyMockSupport = ny EasyMockSupport (); @Test offentlig ugyldig nårReadAndWriteSequencially_thenWorks () {ArticleReader mockArticleReader = easyMockSupport .createMock (ArticleReader.class); IArticleWriter mockArticleWriter = easyMockSupport .createMock (IArticleWriter.class); BaeldungReader baeldungReader = ny BaeldungReader (mockArticleReader, mockArticleWriter); forvent (mockArticleReader.next ()). ogReturn (null); forvent (mockArticleWriter.write ("title", "content")). og Retur (""); easyMockSupport.replayAll (); baeldungReader.readNext (); baeldungReader.write ("tittel", "innhold"); easyMockSupport.verifyAll (); }

Tidligere brukte vi statiske metoder eller merknader for å lage og administrere mocks. Under panseret styres disse statiske og kommenterte spottene av en global EasyMockSupport forekomst.

Her instantierte vi det eksplisitt og tok alle disse spottene under vår egen kontroll, gjennom delegering. Dette kan bidra til å unngå forvirring hvis det er noen navnekonflikter i testkoden vår med EasyMock eller om det er noen lignende tilfeller.

8. Konklusjon

I denne artikkelen introduserte vi kort den grunnleggende bruken av EasyMock, om hvordan du kan generere mock-objekter, registrere og spille av atferd, og kontrollere om de oppførte seg riktig.

I tilfelle du er interessert, sjekk ut denne artikkelen for en sammenligning av EasyMock, Mocket og JMockit.

Som alltid kan den fullstendige implementeringen finnes på Github.


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