Argument matchers van Mockito
Gebruik argument matchers om uw verificaties en stubbings flexibeler en robuuster te maken.
Argument matchers van Mockito is een gratis Testen beheersen: JUnit, Mockito en integratietesten-les op CoddyKit. Dit is les 2 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Testen beheersen: JUnit, Mockito en integratietesten. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Testen beheersen: JUnit, Mockito en integratietesten bevat in totaal 4 lessen.
Flexibel matchen met Mockito
Bij het schrijven van tests van eenheden met Mockito moet je vaak methodeaanroepen verifiëren of mockgedrag configureren op basis van de argumenten die eraan worden doorgegeven. Soms is een exacte overeenkomst voor elk argument niet flexibel genoeg.
Argumentmatchers zijn speciale plaatshouders waarmee je criteria voor argumenten kunt opgeven in plaats van hun exacte waarden. Zo worden je tests robuuster en minder kwetsbaar.
Waarom exacte overeenkomsten tekortschieten
Standaard gebruikt Mockito de methode equals() om argumenten te vergelijken. Dit werkt prima voor eenvoudige typen zoals getallen of tekenreeksen, en voor objecten die equals() correct overschrijven.
- Wat als het exacte object je niet interesseert, maar alleen een specifieke eigenschap ervan?
- Wat als een argument telkens een nieuw object is, maar de inhoud ervan wel belangrijk is?
In deze gevallen kunnen je tests kwetsbaar worden als je uitsluitend op exacte overeenkomsten vertrouwt.
De jokertekenmatcher: `any()`
De eenvoudigste en meest gebruikte argumentmatcher is any(). Deze vertelt Mockito dat voor die argumentpositie elke waarde van een opgegeven type mag overeenkomen.
Gebruik any() wanneer het je alleen gaat om het feit dat een methode is aangeroepen met een waarde van het juiste type, niet om de exacte inhoud ervan.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
interface MyService {
void processData(String message, int count);
}
public class AnyMatcherDemo {
@Test
void testAnyArgument() {
MyService mockService = mock(MyService.class);
mockService.processData("Hello", 5);
// Verify processData was called with ANY String and ANY int
verify(mockService).processData(anyString(), anyInt());
System.out.println("Verified with anyString() and anyInt()!");
}
public static void main(String[] args) {
new AnyMatcherDemo().testAnyArgument();
}
}Typespecifieke `any()`-matchers
Mockito biedt specifieke any()-matchers voor veelgebruikte gegevenstypen. Dat verbetert de leesbaarheid en typeveiligheid:
anyString(): komt overeen met elkeString.anyInt(): komt overeen met elkeint.anyBoolean(): komt overeen met elkeboolean.anyList(),anySet(),anyMap(): komen overeen met elk verzamelingstype.any(MyClass.class): komt overeen met elk exemplaar vanMyClass.
Het is een goede gewoonte om de meest specifieke beschikbare matcher te gebruiken.
`eq()` en matchers combineren
Je kunt argumentmatchers combineren met het matchen van exacte waarden. Er geldt echter een belangrijke regel: zodra je voor *een* argument in een methodeaanroep een argumentmatcher gebruikt, moet je voor *alle* argumenten in die aanroep matchers gebruiken.
Gebruik eq(value) wanneer een specifiek argument exact moet overeenkomen, terwijl voor andere argumenten matchers worden gebruikt.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
interface MyProcessor {
void handle(String type, int id);
}
public class EqAndAnyDemo {
@Test
void testSpecificAndAny() {
MyProcessor mockProcessor = mock(MyProcessor.class);
mockProcessor.handle("EMAIL", 101);
mockProcessor.handle("SMS", 202);
// Verify handle was called with "EMAIL" as type and ANY int as id
verify(mockProcessor).handle(eq("EMAIL"), anyInt());
System.out.println("Verified handle('EMAIL', anyInt())!");
}
public static void main(String[] args) {
new EqAndAnyDemo().testSpecificAndAny();
}
}Matchen op type en nullwaarden
Naast exacte typen of willekeurige waarden biedt Mockito matchers voor specifiekere voorwaarden:
isA(Class> clazz): komt overeen met elk object dat een exemplaar is van de opgegeven klasse of een subklasse daarvan. Functioneel vergelijkbaar metany(Class.class).notNull(): komt overeen met elk argument dat nietnullis.isNull(): komt overeen met elk argument dat *wel*nullis.
Hiermee krijg je zeer nauwkeurige controle over de verwachtingen voor argumenten.
Geavanceerde voorwaarden: `and()`, `or()`
Voor complexe matchsituaties kun je meerdere matchers combineren met logische operatoren. Deze zijn beschikbaar via org.mockito.AdditionalMatchers (of in nieuwere versies soms rechtstreeks via Mockito).
and(matcher1, matcher2): komt overeen als beide matchers waar zijn.or(matcher1, matcher2): komt overeen als een van beide matchers waar is.not(matcher): keert het resultaat van een matcher om.
Zo kun je zeer specifieke voorwaarden voor argumenten samenstellen.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.mockito.AdditionalMatchers.*; // For and/or/gt/lt
interface OrderService {
void placeOrder(int customerId, double amount);
}
public class CombinedMatchersDemo {
@Test
void testCombinedMatchers() {
OrderService mockService = mock(OrderService.class);
mockService.placeOrder(101, 150.0);
mockService.placeOrder(105, 50.0);
// Verify calls where customerId > 100 AND amount > 100.0
verify(mockService).placeOrder(
and(gt(100), lt(1000)), // customerId between 101 and 999
gt(100.0)
);
System.out.println("Verified order with customerId > 100 AND amount > 100!");
}
public static void main(String[] args) {
new CombinedMatchersDemo().testCombinedMatchers();
}
}Aangepast matchen met `argThat()`
Wanneer ingebouwde matchers niet aan je behoeften voldoen, biedt argThat() uitkomst. Hiermee kun je aangepaste matchlogica definiëren met een Hamcrest-matcher of een eenvoudige lambda-expressie.
Dit is bijzonder krachtig voor het vergelijken van complexe objecten op basis van meerdere eigenschappen of interne toestanden.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
class Product {
String name;
double price;
Product(String name, double price) { this.name = name; this.price = price; }
public String getName() { return name; }
public double getPrice() { return price; }
}
interface ProductRepository {
void save(Product product);
}
public class ArgThatDemo {
@Test
void testArgThatMatcher() {
ProductRepository mockRepo = mock(ProductRepository.class);
mockRepo.save(new Product("Laptop", 1200.0));
mockRepo.save(new Product("Mouse", 25.0));
// Verify save was called with a product whose price is > 1000
verify(mockRepo).save(argThat(p -> p.getPrice() > 1000.0));
System.out.println("Verified product with price > 1000 was saved!");
}
public static void main(String[] args) {
new ArgThatDemo().testArgThatMatcher();
}
}Mockgedrag instellen met matchers
Argumentmatchers zijn niet alleen bedoeld voor verificatie. Je kunt ze ook gebruiken bij het instellen van mockgedrag met when().thenReturn(). Zo kan je mock verschillende waarden retourneren of uitzonderingen genereren op basis van de argumenten die hij ontvangt.
Dit is ideaal voor het simuleren van verschillende scenario's waarin een afhankelijkheid zich anders gedraagt afhankelijk van de invoer.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
interface DataService {
String getData(String key);
}
public class StubbingWithMatchers {
@Test
void testStubbingWithAny() {
DataService mockService = mock(DataService.class);
// Stubbing: if getData is called with "config", return "Config Data"
when(mockService.getData(eq("config"))).thenReturn("Config Data");
// Stubbing: if getData is called with ANY other String, return "Default Data"
when(mockService.getData(anyString())).thenReturn("Default Data");
System.out.println("Result 1: " + mockService.getData("config"));
System.out.println("Result 2: " + mockService.getData("user_profile"));
}
public static void main(String[] args) {
new StubbingWithMatchers().testStubbingWithAny();
}
}Verifiëren met matchers
Argumentmatchers zijn essentieel om te verifiëren dat methoden zijn aangeroepen met argumenten die aan specifieke criteria voldoen. Zo weet je zeker dat je code de verwachte interactie met afhankelijkheden heeft, zelfs als de exacte argumentwaarden dynamisch zijn.
Je kunt matchers combineren met verificatiemodi zoals times(count) of atLeast(count) voor krachtigere beweringen.
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
interface Logger {
void log(String level, String message);
}
public class VerificationWithMatchers {
@Test
void testVerificationWithAny() {
Logger mockLogger = mock(Logger.class);
mockLogger.log("INFO", "User logged in.");
mockLogger.log("ERROR", "Failed to save.");
mockLogger.log("INFO", "Data processed.");
// Verify 'log' was called twice with "INFO" and ANY String message
verify(mockLogger, times(2)).log(eq("INFO"), anyString());
System.out.println("Verified 2 INFO logs with any message!");
}
public static void main(String[] args) {
new VerificationWithMatchers().testVerificationWithAny();
}
}Matcheruitdaging
Bekijk de volgende Mockito-configuratie en methodeaanroepen:
MyDatabase mockDb = mock(MyDatabase.class);mockDb.saveRecord("user_1", "John Doe");mockDb.saveRecord("user_2", "Jane Smith");
Welke verify()-aanroep controleert correct dat saveRecord minstens één keer is aangeroepen met een sleutel die begint met "user_" en *een willekeurige* tekenreeks als waarde?
Samenvatting: argumentmatchers
In deze les heb je de argumentmatchers van Mockito onder de knie gekregen, een krachtige functie voor het maken van flexibele en robuuste tests:
- We hebben
any()en de typespecifieke varianten ervan, zoalsanyString(), bekeken voor het matchen van elke waarde. - Je hebt geleerd hoe je
eq()combineert met andere matchers voor specifieke waarden. - We hebben geavanceerde matchers behandeld, zoals
isA(),notNull()en logische operatoren (and(),or()). - Je hebt gezien hoe
argThat()volledig aangepaste matchlogica mogelijk maakt. - Tot slot hebben we matchers toegepast bij zowel het instellen van mockgedrag (
when()) als verificatie (verify()).
Door argumentmatchers effectief te gebruiken, worden je tests minder afhankelijk van exacte, starre waarden en richten ze zich meer op het verwachte gedrag. Daardoor zijn ze beter bestand tegen wijzigingen.
Leer Testen beheersen: JUnit, Mockito en integratietesten met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 12
- Lessen
- 48
Veelgestelde vragen
Is de les “Argument matchers van Mockito” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Testen beheersen: JUnit, Mockito en integratietesten, waaronder “Argument matchers van Mockito”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Testen beheersen: JUnit, Mockito en integratietesten bevat in totaal 4 lessen.
Wat leer ik in “Argument matchers van Mockito”?
Gebruik argument matchers om uw verificaties en stubbings flexibeler en robuuster te maken. Je oefent met Testen beheersen: JUnit, Mockito en integratietesten door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Testen beheersen: JUnit, Mockito en integratietesten te beginnen?
Ervaring vooraf is niet nodig. Testen beheersen: JUnit, Mockito en integratietesten op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Argument matchers van Mockito”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Testen beheersen: JUnit, Mockito en integratietesten?
Ja. Elke les over Testen beheersen: JUnit, Mockito en integratietesten bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Returnwaarden stubben
- Argument matchers van Mockito
- Echte objecten spioneren
- Exceptions opwerpen en opeenvolgende aanroepen