Mockito ArgumentCaptor gebruiken

1. Overzicht

In deze zelfstudie behandelen we een veelvoorkomend geval van het gebruik van Mockito ArgumentCaptor in onze unit tests.

Als alternatief voor andere Mockito. Verifiëren use cases, zie ons Mockito Verify Cookbook.

2. Met behulp van ArgumentCaptor

ArgumentCaptor stelt ons in staat een argument vast te leggen dat aan een methode is doorgegeven om het te inspecteren. Dit is vooral handig als we geen toegang hebben tot het argument buiten de methode die we willen testen.

Beschouw bijvoorbeeld een E-mailservice klas met een sturen methode die we willen testen:

openbare klasse EmailService {privé DeliveryPlatform-platform; openbare EmailService (DeliveryPlatform-platform) {this.platform = platform; } public void send (String to, String subject, String body, boolean html) {Format format = Format.TEXT_ONLY; if (html) {format = Format.HTML; } E-mail e-mail = nieuwe e-mail (aan, onderwerp, hoofdtekst); email.setFormat (formaat); platform.deliver (e-mail); } ...}

In E-mailservice.sturen, merk op hoe platform.deliver neemt een nieuwe E-mail als argument. Als onderdeel van onze test willen we controleren of het formaatveld van het nieuwe E-mail ingesteld op Formaat.HTML. Om dit te doen, moeten we het argument dat wordt doorgegeven, vastleggen en inspecteren platform.deliver.

Laten we eens kijken hoe we kunnen gebruiken ArgumentCaptor om ons te helpen.

2.1. Stel de unit-test op

Laten we eerst onze unit-testklasse maken:

@RunWith (MockitoJUnitRunner.class) openbare klasse EmailServiceUnitTest {@Mock DeliveryPlatform-platform; @InjectMocks EmailService emailService; ...}

We gebruiken de @Bespotten annotatie om te bespotten Bezorgplatform, die automatisch in ons wordt geïnjecteerd E-mailservice met de @InjectMocks annotatie. Raadpleeg ons artikel over Mockito-annotaties voor meer informatie.

2.2. Voeg een ArgumentCaptor Veld

Ten tweede, laten we een nieuwe toevoegen ArgumentCaptor veld van het type E-mail om ons vastgelegde argument op te slaan:

@Captor ArgumentCaptor emailCaptor;

2.3. Leg het argument vast

Ten derde, laten we gebruiken Mockito. Verifiëren met de ArgumentCaptor om het E-mail:

Mockito.verify (platform) .levering (emailCaptor.capture ());

We kunnen dan de vastgelegde waarde ophalen en deze als een nieuwe opslaan E-mail voorwerp:

E-mail emailCaptorValue = emailCaptor.getValue ();

2.4. Inspecteer de vastgelegde waarde

Laten we tot slot de hele test bekijken met een bewering om de gevangengenomen te inspecteren E-mail voorwerp:

@Test openbaar ongeldig whenDoesSupportHtml_expectHTMLEmailFormat () {String to = "[e-mail beveiligd]"; String subject = "ArgumentCaptor gebruiken"; String body = "Hé, laten we ArgumentCaptor gebruiken"; emailService.send (to, subject, body, true); Mockito.verify (platform) .levering (emailCaptor.capture ()); E-mailwaarde = emailCaptor.getValue (); assertEquals (Format.HTML, value.getFormat ()); }

3. Stubbing vermijden

Hoewel we kunnen een ArgumentCaptor met stoten, we moeten dit in het algemeen vermijden. Ter verduidelijking: in Mockito betekent dit over het algemeen het gebruik van een ArgumentCaptor met Mockito. Wanneer. Bij stoten moeten we een ArgumentMatcher in plaats daarvan.

Laten we eens kijken naar een paar redenen waarom we stoten moeten vermijden.

3.1. Verminderde leesbaarheid van de test

Overweeg eerst een eenvoudige test:

Inloggegevens inloggegevens = nieuwe inloggegevens ("baeldung", "correct_password", "correct_key"); Mockito.when (platform.authenticate (Mockito.eq (referenties))) .thenReturn (AuthenticationStatus.AUTHENTICATED); assertTrue (emailService.authenticatedSuccessfully (referenties));

Hier gebruiken we Mockito.eq (inloggegevens) om aan te geven wanneer de mock een object moet retourneren.

Overweeg vervolgens dezelfde test met een ArgumentCaptor in plaats daarvan:

Inloggegevens inloggegevens = nieuwe inloggegevens ("baeldung", "correct_password", "correct_key"); Mockito.when (platform.authenticate (credentialsCaptor.capture ())) .thenReturn (AuthenticationStatus.AUTHENTICATED); assertTrue (emailService.authenticatedSuccessfully (referenties)); assertEquals (referenties, credentialsCaptor.getValue ());

Merk in tegenstelling tot de eerste test op hoe we een extra bewering op de laatste regel moeten uitvoeren om hetzelfde te doen als Mockito.eq (inloggegevens).

Merk ten slotte op dat het niet meteen duidelijk is wat referentiesCaptor.capture () verwijst naar. Dit komt omdat we de captor buiten de regel moeten maken waarop we deze gebruiken, wat de leesbaarheid vermindert.

3.2. Minder defect Lokalisatie

Een andere reden is dat if emailService.authenticatedSuccessfully roept niet platform.authenticate, krijgen we een uitzondering:

org.mockito.exceptions.base.MockitoException: er is geen argumentwaarde vastgelegd!

Dit komt doordat onze stubbed-methode geen argument bevat. Het eigenlijke probleem zit echter niet in onze test zelf, maar in de feitelijke methode die we testen.

Met andere woorden, het leidt ons verkeerd naar een uitzondering in de test, terwijl het eigenlijke defect in de methode zit die we testen.

4. Conclusie

In deze korte tutorial hebben we gekeken naar een algemeen gebruik van het gebruik van ArgumentCaptor. We hebben ook gekeken naar de redenen om het gebruik te vermijden ArgumentCaptor met stoten. Zoals gewoonlijk zijn al onze codevoorbeelden beschikbaar op GitHub.