Argumentmatchere i Mockito
Bruk argumentmatchere for å gjøre verifiseringer og stubbing mer fleksible og robuste.
Argumentmatchere i Mockito er en gratis leksjon i Testing i praksis: JUnit, Mockito og integrasjonstester på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Testing i praksis: JUnit, Mockito og integrasjonstester, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Testing i praksis: JUnit, Mockito og integrasjonstester inneholder totalt 4 leksjoner.
Fleksibel samsvaring med Mockito
Når du skriver enhetstester med Mockito, må du ofte verifisere metodekall eller konfigurere oppførselen til mockobjekter basert på argumentene som sendes til dem. Noen ganger er det ikke fleksibelt nok å kreve et nøyaktig samsvar for hvert argument.
Argumentmatchere er spesielle plassholdere som lar deg angi kriterier for argumenter i stedet for de nøyaktige verdiene deres. Dermed blir testene mer robuste og mindre sårbare for endringer.
Hvorfor nøyaktig samsvar ikke alltid er nok
Som standard bruker Mockito metoden equals() til å sammenligne argumenter. Dette fungerer utmerket for enkle typer som tall eller strenger, og for objekter som overstyrer equals() på riktig måte.
- Hva om De ikke bryr Dem om det nøyaktige objektet, men bare om en bestemt egenskap ved det?
- Hva om argumentet er et nytt objekt hver gang, men det er innholdet som betyr noe?
I slike tilfeller kan tester bli skjøre hvis De utelukkende baserer Dem på eksakte treff.
Matcher med jokertegn: `any()`
Den enkleste og mest brukte argumentmatcheren er any(). Den ber Mockito matche enhver verdi av en angitt type på denne argumentplassen.
Bruk any() når De bare er opptatt av at en metode ble kalt med en eller annen verdi av riktig type, ikke det nøyaktige innholdet.
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();
}
}Typespesifikke `any()`-matchere
Mockito tilbyr spesifikke any()-matchere for vanlige datatyper, noe som gir bedre lesbarhet og typesikkerhet:
anyString(): Matcher enhverString.anyInt(): Matcher enhverint.anyBoolean(): Matcher enhverboolean.anyList(),anySet(),anyMap(): Matcher enhver samlingstype.any(MyClass.class): Matcher enhver instans avMyClass.
Det er god praksis å bruke den mest spesifikke matcheren som er tilgjengelig.
Kombinere `eq()` og matchere
De kan kombinere argumentmatchere med matching av eksakte verdier. Det finnes imidlertid en viktig regel: så snart De bruker en argumentmatcher for *ett hvilket som helst* argument i et metodekall, må De bruke matchere for *alle* argumentene i dette kallet.
Bruk eq(value) når De trenger et eksakt treff for et bestemt argument, mens andre argumenter bruker matchere.
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();
}
}Matching etter type og null-verdi
I tillegg til eksakte typer eller vilkårlige verdier tilbyr Mockito matchere for mer spesifikke betingelser:
isA(Class> clazz): Matcher ethvert objekt som er en instans av den angitte klassen (eller en underklasse). Funksjonelt tilsvarendeany(Class.class).notNull(): Matcher ethvert argument som ikke ernull.isNull(): Matcher ethvert argument som *er*null.
Disse gir finkornet kontroll over forventningene til argumentene.
Avanserte betingelser: `and()`, `or()`
Ved komplekse matchingsscenarier kan De kombinere flere matchere ved hjelp av logiske operatorer. Disse er tilgjengelige fra org.mockito.AdditionalMatchers (eller noen ganger direkte fra Mockito i nyere versjoner).
and(matcher1, matcher2): Matcher hvis begge matcherene er sanne.or(matcher1, matcher2): Matcher hvis minst én av matcherene er sann.not(matcher): Snur resultatet av en matcher.
Dette gjør det mulig å bygge svært spesifikke betingelser for argumenter.
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();
}
}Tilpasset matching med `argThat()`
Når de innebygde matcherene ikke dekker behovene Deres, kommer argThat() til unnsetning. Den lar Dem definere egendefinert matchingslogikk ved hjelp av en Hamcrest-matcher eller et enkelt lambda-uttrykk.
Dette er svært kraftig når komplekse objekter skal sammenlignes basert på flere egenskaper eller intern tilstand.
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();
}
}Stubbing med matchere
Argumentmatchere brukes ikke bare til verifisering. De kan også brukes når De stubber oppførselen til en mock med when().thenReturn(). Dette gjør det mulig for mocken å returnere ulike verdier eller kaste unntak basert på argumentene den mottar.
Dette er perfekt for å simulere ulike scenarier der en avhengighet oppfører seg forskjellig basert på inndata.
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();
}
}Verifisering med matchere
Argumentmatchere er grunnleggende for å verifisere at metoder ble kalt med argumenter som oppfyller bestemte kriterier. Dette sikrer at koden samhandler med avhengighetene sine som forventet, selv når de nøyaktige argumentverdiene varierer.
De kan kombinere matchere med verifiseringsmoduser som times(count) eller atLeast(count) for mer kraftfulle påstander.
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();
}
}Matcher-utfordring
Se på følgende Mockito-oppsett og metodekall:
MyDatabase mockDb = mock(MyDatabase.class);mockDb.saveRecord("user_1", "John Doe");mockDb.saveRecord("user_2", "Jane Smith");
Hvilket verify()-kall vil på riktig måte kontrollere at saveRecord ble kalt minst én gang med en nøkkel som starter med "user_" og *en hvilken som helst* streng som verdi?
Oppsummering: Argumentmatchere
I denne leksjonen har De lært å bruke Mockitos argumentmatchere, en kraftig funksjon for å lage fleksible og robuste tester:
- Vi utforsket
any()og typespesifikke varianter somanyString()for matching av enhver verdi. - De lærte å kombinere
eq()med andre matchere for bestemte verdier. - Vi gikk gjennom avanserte matchere som
isA(),notNull()og logiske operatorer (and(),or()). - De så hvordan
argThat()gjør det mulig å definere helt egendefinert matchingslogikk. - Til slutt brukte vi matchere både ved stubbing (
when()) og verifisering (verify()).
Ved å bruke argumentmatchere effektivt blir testene mindre avhengige av eksakte, rigide verdier og mer rettet mot forventet oppførsel. Dermed tåler de endringer bedre.
Lær deg Testing i praksis: JUnit, Mockito og integrasjonstester med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 12
- Leksjoner
- 48
Ofte stilte spørsmål
Er leksjonen «Argumentmatchere i Mockito» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Testing i praksis: JUnit, Mockito og integrasjonstester, inkludert «Argumentmatchere i Mockito», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Testing i praksis: JUnit, Mockito og integrasjonstester inneholder totalt 4 leksjoner.
Hva lærer jeg i «Argumentmatchere i Mockito»?
Bruk argumentmatchere for å gjøre verifiseringer og stubbing mer fleksible og robuste. Du øver på Testing i praksis: JUnit, Mockito og integrasjonstester med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Testing i praksis: JUnit, Mockito og integrasjonstester?
Ingen tidligere erfaring er nødvendig. Testing i praksis: JUnit, Mockito og integrasjonstester på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Argumentmatchere i Mockito»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Testing i praksis: JUnit, Mockito og integrasjonstester-leksjonen?
Ja. Alle Testing i praksis: JUnit, Mockito og integrasjonstester-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Stubbing av returverdier
- Argumentmatchere i Mockito
- Spionering på ekte objekter
- Kasting av exceptions og påfølgende kall