Java >> Java tutorial >  >> Tag >> JUnit

JUnit 5 Tutorial:Skrivning af parametriserede tests

Dette blogindlæg beskriver, hvordan vi kan skrive parameteriserede tests med JUnit 5. Efter at vi har afsluttet dette blogindlæg, har vi:

  • Kan få de nødvendige afhængigheder med Maven og Gradle.
  • Vid, hvordan vi kan tilpasse visningsnavnet for hver metodeankaldelse.
  • Forstå, hvordan vi kan bruge forskellige argumentkilder.
  • Kan skrive brugerdefinerede argumentkonvertere.

Lad os starte med at få de nødvendige afhængigheder.

Få de nødvendige afhængigheder

Før vi kan skrive parameteriserede test med JUnit 5, skal vi sikre, at junit-jupiter-params afhængighed findes fra klassestien. Hvis vi bruger junit-jupiter aggregator artefakt, behøver vi ikke at gøre noget, fordi alle de nødvendige afhængigheder allerede er tilføjet til klassestien. På den anden side, hvis vi ikke bruger junit-jupiter aggregator-artefakt, er vi nødt til at foretage nogle ændringer i vores build-script.

Hvis vi bruger Maven, skal vi tilføje junit-jupiter-params afhængighed af test omfang. Vi kan gøre dette ved at tilføje følgende kodestykke til dependencies sektion af vores POM-fil:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

Hvis vi bruger Gradle, skal vi tilføje junit-jupiter-params afhængighed af testImplementation afhængighedskonfiguration. Vi kan gøre dette ved at tilføje følgende uddrag til vores build.gradle fil:

testImplementation(
        'org.junit.jupiter:junit-jupiter-params:5.8.2'
)

Lad os gå videre og skrive vores første parameteriserede test med JUnit 5.

Skrivning af vores første parametriserede test

Hvis vores testmetode kun tager én metodeparameter, er det enten en String eller en primitiv type understøttet af @ValueSource annotation (byte , char , double , float , int , long eller short ), kan vi skrive en parameteriseret test med JUnit 5 ved at følge disse trin:

  1. Tilføj en ny testmetode til vores testklasse, og sørg for, at denne metode tager en String objekt som en metodeparameter.
  2. Konfigurer visningsnavnet for testmetoden.
  3. Kommenter testmetoden med @ParameterizedTest anmærkning. Denne annotation identificerer parameteriserede testmetoder.
  4. Angiv de metodeparametre, som videregives til vores testmetode. Fordi vores testmetode tager én String objekt som metodeparameter, kan vi levere dets metodeparametre ved at annotere vores testmetode med @ValueSource anmærkning.

Efter at vi har tilføjet en ny parameteriseret test til vores testklasse, ser dens kildekode ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@DisplayName("Pass the method parameters provided by the @ValueSource annotation")
class ValueSourceExampleTest {

    @DisplayName("Should pass a non-null message to our test method")
    @ParameterizedTest
    @ValueSource(strings = {"Hello", "World"})
    void shouldPassNonNullMessageAsMethodParameter(String message) {
        assertNotNull(message);
    }
}

Når vi kører vores parameteriserede test, skulle vi se et output, der ser ud som følger:

Pass the method parameters provided by the @ValueSource annotation
|_ Should pass a non-null message to our test method
   |_ [1] Hello
   |_ [2] World

Selvom dette output ser ret rent ud, ønsker vi nogle gange at give vores eget visningsnavn for hver metodekald. Lad os finde ud af, hvordan vi kan gøre det.

Tilpasning af visningsnavnet for hver metodekald

Vi kan tilpasse visningsnavnet for hver metodekald ved at indstille værdien af ​​@ParameterizedTest annotationens name attribut. Denne attribut understøtter følgende pladsholdere:

  • {displayName} :Visningsnavnet på testmetoden.
  • {index} :Indekset for den aktuelle påkaldelse. Bemærk, at indekset for den første påkaldelse er ét.
  • {arguments} :En kommasepareret liste, der indeholder alle argumenter, der er sendt til testmetoden.
  • {argumentsWithNames} :En kommasepareret liste, der indeholder alle argumenter (inklusive navnet på metodeparameteren), der sendes til testmetoden.
  • {i} :Den faktiske metodeparameter (i angiver indekset for metodeparameteren). Bemærk, at indekset for den første metodeparameter er nul.

Lad os give vores testmetode et brugerdefineret visningsnavn. Dette visningsnavn skal vise indekset for den aktuelle påkaldelse og den angivne metodeparameter. Efter at vi har konfigureret det brugerdefinerede visningsnavn for hver metodeankaldelse, ser kildekoden for vores testklasse ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@DisplayName("Pass the method parameters provided by the @ValueSource annotation")
class ValueSourceExampleTest {

    @DisplayName("Should pass a non-null message to our test method")
    @ParameterizedTest(name = "{index} => message=''{0}''")
    @ValueSource(strings = {"Hello", "World"})
    void shouldPassNonNullMessageAsMethodParameter(String message) {
        assertNotNull(message);
    }
}

Når vi kører vores parameteriserede test, skulle vi se et output, der ser ud som følger:

Pass the method parameters provided by the @ValueSource annotation
|_ Should pass a non-null message to our test method
   |_ 1 => message='Hello'
   |_ 2 => message='World'

Som vi husker, er @ValueSource annotering er et godt valg, hvis vores testmetode kun tager én metodeparameter, der understøttes af @ValueSource anmærkning. Men det meste af tiden er dette ikke tilfældet. Dernæst vil vi finde ud af, hvordan vi kan løse dette problem ved at bruge forskellige argumentkilder.

Brug af argumentkilder

@ValueSource annotation er den enkleste argumentkilde, der understøttes af JUnit 5. JUnit 5 understøtter dog også andre argumentkilder. Alle understøttede argumentkilder er konfigureret ved hjælp af annoteringer fundet fra org.junit.jupiter.params.provider pakke.

Dette afsnit beskriver, hvordan vi kan bruge de mere komplekse argumentkilder leveret af JUnit 5. Lad os starte med at finde ud af, hvordan vi kan videregive enum værdier til vores parametriserede test.

Bestå Enum-værdier til vores parametrerede test

Hvis vores parametrerede test tager én enum værdi som metodeparameter, skal vi annotere vores testmetode med @EnumSource annotation og specificer de enum-værdier, der overføres til vores testmetode.

Lad os antage, at vi skal skrive en parameteriseret test, der tager værdien Pet enum som metodeparameter. Kildekoden til Pet enum ser ud som følger:

enum Pet {
    CAT,
    DOG;
}

Hvis vi vil videregive alle enum værdier til vores testmetode, skal vi annotere vores testmetode med @EnumSource annotation og angiv enum hvis værdier overføres til vores testmetode. Når vi har gjort dette, ser kildekoden til vores testklasse således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@DisplayName("Pass enum values to our test method")
class EnumSourceExampleTest {

    @DisplayName("Should pass non-null enum values as method parameters")
    @ParameterizedTest(name = "{index} => pet=''{0}''")
    @EnumSource(Pet.class)
    void shouldPassNonNullEnumValuesAsMethodParameter(Pet pet) {
        assertNotNull(pet);
    }
}

Når vi kører denne testmetode, ser vi, at JUnit 5 passerer alle værdier af Pet enum til vores testmetode:

Pass enum values to our test method
|_ Should pass non-null enum values as method parameters
   |_ 1 => pet='CAT'
   |_ 2 => pet='DOG'

Hvis vi ønsker at angive enum værdier, der overføres til vores testmetode, kan vi angive enum værdier ved at indstille værdien af ​​@EnumSource annotationens names attribut. Lad os sikre, at værdien:Pet.CAT videregives til vores testmetode.

Efter at vi har angivet den brugte enum-værdi, ser kildekoden for vores testklasse ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@DisplayName("Pass enum values to our test method")
class EnumSourceExampleTest {

    @DisplayName("Should pass only the specified enum value as a method parameter")
    @ParameterizedTest(name = "{index} => pet=''{0}''")
    @EnumSource(value = Pet.class, names = {"CAT"})
    void shouldPassNonNullEnumValueAsMethodParameter(Pet pet) {
        assertNotNull(pet);
    }
}

Når vi kører denne testmetode, ser vi, at JUnit 5 kun passerer værdien:Pet.CAT til vores testmetode:

Pass enum values to our test method
|_ Should pass non-null enum values as method parameters
   |_ 1 => pet='CAT'

Vi har nu lært, hvordan vi kan bruge to forskellige argumentkilder, der giver os mulighed for at videregive en metodeparameter til vores testmetode. Men det meste af tiden ønsker vi at videregive flere metodeparametre til vores parameteriserede test. Dernæst vil vi finde ud af, hvordan vi kan løse dette problem ved at bruge CSV-formatet.

Oprettelse af vores testdata ved at bruge CSV-formatet

Hvis vi skal sende flere argumenter til den påberåbte testmetode, og de leverede testdata kun bruges af én testmetode (eller nogle få testmetoder), kan vi konfigurere vores testdata ved at bruge @CsvSource anmærkning. Når vi tilføjer denne annotation til en testmetode, skal vi konfigurere testdataene ved at bruge en matrix af String genstande. Når vi angiver vores testdata, skal vi følge disse regler:

  • Én String objekt skal indeholde alle argumenter for én metodekald.
  • De forskellige argumentværdier skal adskilles med et komma.
  • Argumentværdierne fundet fra hver linje skal bruge samme rækkefølge som metodeparametrene for vores testmetode.

Lad os konfigurere de argumenter, der sendes til sum() metode. Denne metode tager tre metodeparametre:de første to metodeparametre indeholder to int værdier og den tredje metodeparameter angiver den forventede sum af den angivne int værdier.

Efter at vi har konfigureret testdataene for vores parameteriserede test, ser kildekoden for vores testklasse ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the @CsvSource annotation")
class CsvSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    @CsvSource({
            "1, 1, 2",
            "2, 3, 5"
    })
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }
}

Selvom dette ser ret rent ud, har vi nogle gange så mange testdata, at det ikke giver mening at tilføje det til vores testklasse, fordi vores testklasse ville blive ulæselig. Lad os finde ud af, hvordan vi kan indlæse testdata, der er sendt til sum() metode fra en CSV-fil.

Indlæsning af vores testdata fra en CSV-fil

Vi kan indlæse vores testdata fra en CSV-fil ved at følge disse trin:

Først , skal vi oprette en CSV-fil, der indeholder vores testdata og lægge denne fil til klassestien. Når vi tilføjer vores testdata til den oprettede CSV-fil, skal vi følge disse regler:

  • En linje skal indeholde alle argumenter for én metodepåkaldelse.
  • De forskellige argumentværdier skal adskilles med et komma.
  • Argumentværdierne fundet fra hver linje skal bruge samme rækkefølge som metodeparametrene for vores testmetode.

test-data.csv fil konfigurerer de testdata, der sendes til sum() metode. Denne fil er fundet fra src/test/resources mappe, og dens indhold ser ud som følger:

1,1,2
2,3,5
3,5,8

Anden , skal vi annotere vores testmetode med @CsvFileSource annotering og konfigurer placeringen af ​​vores CSV-fil. Når vi har gjort dette, ser kildekoden til vores testklasse således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the test-data.csv file")
class CsvFileSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    @CsvFileSource(resources = "/test-data.csv")
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }
}

Vi kan nu videregive flere metodeparametre til vores parameteriserede test. Men fangsten er, at metodeparametrene for vores parameteriserede test skal understøttes af DefaultArgumentConverter klasse. Dens Javadoc siger, at:

DefaultArgumentConverter er i stand til at konvertere fra strenge til et antal primitive typer og deres tilsvarende indpakningstyper (Byte, Short, Integer, Long, Float og Double), dato- og tidstyper fra java.time-pakken og nogle yderligere almindelige Java typer såsom File, BigDecimal, BigInteger, Currency, Locale, URI, URL, UUID osv.

Dernæst vil vi finde ud af, hvordan vi kan løse dette problem ved at bruge en fabriksmetode og en brugerdefineret ArgumentsProvider .

Oprettelse af vores testdata ved at bruge en fabriksmetode

Hvis alle parameteriserede tests, der bruger de oprettede testdata, findes fra den samme testklasse, og logikken, der skaber testdataene, ikke er "for kompleks", bør vi oprette vores testdata ved at bruge en fabriksmetode.

Hvis vi vil bruge denne tilgang, skal vi tilføje en static fabriksmetode til vores testklasse og implementer denne metode ved at følge disse regler:

  • Fabriksmetoden må ikke tage nogen metodeparametre.
  • Fabriksmetoden skal returnere en Stream , Iterable , Iterator , eller en matrix af Arguments genstande. Objektet, der returneres af vores fabriksmetode, indeholder argumenterne for alle testmetodeankaldelser.
  • En Arguments objekt skal indeholde alle argumenter for en enkelt testmetodeankaldelse.
  • Vi kan oprette en ny Arguments objekt ved at kalde static of() metoden for Arguments interface. Argumenterne leveret til of() metoden videregives til vores testmetode, når den påkaldes af JUnit 5. Det er derfor, de angivne argumenter skal bruge samme rækkefølge som metodeparametrene for vores testmetode.

Lad os demonstrere disse regler ved at implementere en fabriksmetode, der skaber testdataene, som sendes til sum() metode (vi har allerede brugt denne metode i de foregående eksempler). Efter at vi har implementeret denne fabriksmetode, ser kildekoden til vores testklasse ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the sumProvider() method")
class MethodSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }

    private static Stream<Arguments> sumProvider() {
        return Stream.of(
                Arguments.of(1, 1, 2),
                Arguments.of(2, 3, 5)
        );
    }
}

Efter at vi har implementeret denne metode, skal vi sikre, at dens returværdi bruges, når JUnit 5 kører vores parameteriserede testmetode. Vi kan gøre dette ved at følge disse trin:

  1. Kommenter vores testmetode med @MethodSource anmærkning.
  2. Konfigurer navnet på den fabriksmetode, der opretter vores testdata.

Efter at vi har foretaget de nødvendige ændringer af vores testklasse, ser dens kildekode ud som følger:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the sumProvider() method")
class MethodSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    @MethodSource("sumProvider")
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }

    private static Stream<Arguments> sumProvider() {
        return Stream.of(
                Arguments.of(1, 1, 2),
                Arguments.of(2, 3, 5)
        );
    }
}

Denne tilgang fungerer relativt godt, så længe fabriksmetoden er enkel, og alle testmetoder, der anvender fabriksmetoden, findes fra samme testklasse. Hvis en af ​​disse betingelser er false , skal vi implementere en brugerdefineret ArgumentsProvider .

Oprettelse af vores testdata ved at bruge en tilpasset argumentudbyder

Hvis testmetoderne, der bruger vores testdata, findes fra forskellige testklasser, eller logikken, der skaber de nødvendige testdata, er så kompleks, at vi ikke ønsker at tilføje dem til vores testklasse, skal vi oprette en brugerdefineret ArgumentsProvider .

Vi kan gøre dette ved at oprette klasse, der implementerer ArgumentsProvider interface. Efter at vi har oprettet denne klasse, skal vi implementere provideArguments() metode, der returnerer en Stream af Arguments genstande. Når vi opretter den returnerede Stream objekt, skal vi følge disse regler:

  • Det returnerede objekt skal indeholde argumenterne for alle testmetodekald.
  • En Arguments objekt skal indeholde alle argumenter for en enkelt testmetodeankaldelse.
  • Vi kan oprette en ny Arguments objekt ved at kalde static of() metoden for Arguments interface. Argumenterne leveret til of() metoden videregives til vores testmetode, når den påkaldes af JUnit 5. Det er derfor, de angivne argumenter skal bruge samme rækkefølge som metodeparametrene for vores testmetode.

Lad os oprette en tilpasset ArgumentsProvider som giver de testdata, der er videregivet til sum() metode. Vi kan gøre dette ved at følge disse trin:

Først , har vi skrevet en brugerdefineret ArgumentsProvider klasse, som returnerer testdata, der er sendt til sum() metode.

Efter at vi har oprettet en brugerdefineret ArgumentsProvider klasse, ser kildekoden til vores testklasse således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the CustomArgumentProvider class")
class ArgumentsSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }

    static class CustomArgumentProvider implements ArgumentsProvider {

        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
            return Stream.of(
                    Arguments.of(1, 1, 2),
                    Arguments.of(2, 3, 5)
            );
        }
    }
}

Anden , skal vi konfigurere den brugte ArgumentsProvider ved at annotere vores testmetode med @ArgumentsSource anmærkning. Når vi har gjort dette, ser kildekoden til vores testklasse således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Should pass the method parameters provided by the CustomArgumentProvider class")
class ArgumentsSourceExampleTest {

    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    @ArgumentsSource(CustomArgumentProvider.class)
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }

    static class CustomArgumentProvider implements ArgumentsProvider {

        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
            return Stream.of(
                    Arguments.of(1, 1, 2),
                    Arguments.of(2, 3, 5)
            );
        }
    }
}

Vi kan nu oprette vores testdata ved at bruge fabriksmetoder og brugerdefinerede ArgumentsProvider klasser. Men selvom disse metoder tillader os at ignorere begrænsningerne i DefaultArgumentConverter klasse, nogle gange ønsker vi at levere vores testdata ved at bruge strenge, fordi dette hjælper os med at skrive test, der er nemmere at læse end test, der bruger fabriksmetoder eller brugerdefinerede ArgumentsProvider klasser.

Dernæst vil vi finde ud af, hvordan vi kan løse dette problem ved at bruge en brugerdefineret ArgumentConverter .

Brug af en brugerdefineret argumentkonverter

En ArgumentConverter har kun ét ansvar:det konverterer kildeobjektet til en instans af en anden type. Hvis konverteringen mislykkes, skal den afgive en ArgumentConversionException .

Lad os oprette en ArgumentConverter der kan konvertere en String objekt til en Message objekt. Message klasse er en simpel indpakningsklasse, der blot ombryder meddelelsen givet som et konstruktørargument. Dens kildekode ser ud som følger:

final class Message {

    private final String message;

    Message(String message) {
        this.message = message;
    }

    String getMessage() {
        return message;
    }
}

Vi kan oprette vores brugerdefinerede ArgumentConverter ved at følge disse trin:

Først , skal vi oprette en klasse kaldet MessageConverter der implementerer ArgumentConverter interface. Efter at vi har oprettet denne klasse, ser dens kildekode ud som følger:

import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;

final class MessageConverter implements ArgumentConverter {

    @Override
    public Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
        
    }
}

Anden , skal vi implementere convert() metode ved at følge disse trin:

  1. Smid en ny ArgumentConversionException hvis kildeobjektet ikke er gyldigt. Kildeobjektet skal være en String det er ikke null eller tom.
  2. Opret en ny Message objekt og returner det oprettede objekt.

Efter at vi har implementeret convert() metode, kildekoden til MessageConverter klasse ser ud som følger:

import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;

final class MessageConverter implements ArgumentConverter {

    @Override
    public Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
        checkSource(source);

        String sourceString = (String) source;
        return new Message(sourceString);
    }

    private void checkSource(Object source) {
        if (source == null) {
            throw new ArgumentConversionException("Cannot convert null source object");
        }

        if (!source.getClass().equals(String.class)) {
            throw new ArgumentConversionException(
                    "Cannot convert source object because it's not a string"
            );
        }

        String sourceString = (String) source;
        if (sourceString.trim().isEmpty()) {
            throw new ArgumentConversionException(
                    "Cannot convert an empty source string"
            );
        }
    }
}

Efter at vi har oprettet vores brugerdefinerede ArgumentConverter , skal vi oprette en parameteriseret test, som bruger vores tilpassede ArgumentConverter . Vi kan oprette denne test ved at følge disse trin:

Først , skal vi oprette en ny parameteriseret testmetode ved at følge disse trin:

  1. Tilføj en ny parameteriseret testmetode til vores testklasse, og sørg for, at metoden tager to Message objekter som metodeparametre.
  2. Kommenter testmetoden med @CsvSource annotering og konfigurer testdataene ved at bruge CSV-formatet.
  3. Bekræft, at Message objekter angivet som metodeparametre indeholder den samme besked.

Efter at vi har oprettet vores testmetode, ser kildekoden til vores testklasse således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Pass converted Message objects to our test method")
class MessageConverterExampleTest {

    @DisplayName("Should pass same messages as method parameters")
    @ParameterizedTest(name = "{index} => actual={0}, expected={1}")
    @CsvSource({
            "Hello, Hello",
            "Hi, Hi",
    })
    void shouldPassMessages(Message actual, Message expected) {
        assertEquals(expected.getMessage(), actual.getMessage());
    }
}

Anden , skal vi konfigurere ArgumentConverter der skaber argumenterne videregivet til vores testmetode. Vi kan gøre dette ved at annotere metodeparametrene med @ConvertWith anmærkning. Når vi gør dette, skal vi konfigurere den brugte ArgumentConverter ved at indstille værdien af ​​@ConvertWith annotationens value attribut.

Efter at vi har konfigureret den brugte ArgumentConverter , kildekoden til vores testklasse ser således ud:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.converter.ConvertWith;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Pass converted Message objects to our test method")
class MessageConverterExampleTest {

    @DisplayName("Should pass same messages as method parameters")
    @ParameterizedTest(name = "{index} => actual={0}, expected={1}")
    @CsvSource({
            "Hello, Hello",
            "Hi, Hi",
    })
    void shouldPassMessages(@ConvertWith(MessageConverter.class) Message actual,
                            @ConvertWith(MessageConverter.class) Message expected) {
        assertEquals(expected.getMessage(), actual.getMessage());
    }
}

Vi kan nu skrive parameteriserede tests med JUnit 5. Lad os opsummere, hvad vi lærte fra dette blogindlæg.

Oversigt

Dette blogindlæg har lært os syv ting:

  • Før vi kan skrive parameteriserede test med JUnit 5, skal vi sikre, at junit-jupiter-params afhængighed findes fra klassestien.
  • Vi er nødt til at annotere vores parameteriserede testmetode med @ParameterizedTest anmærkning.
  • Vi kan tilpasse visningsnavnet for hver metodeankaldelse ved at indstille værdien af ​​@ParameterizedTest annotationens name attribut.
  • Når vi konfigurerer vores testdata, skal vores testdata bruge samme rækkefølge som metodeparametrene for vores testmetode.
  • Hvis vi ønsker at videregive "komplekse" objekter til parameteriserede test, som findes fra den samme testklasse, og logikken, der skaber disse argumenter, ikke er "for kompleks", bør vi oprette disse argumenter ved at bruge en fabriksmetode.
  • Hvis testmetoderne, der bruger vores testdata, findes fra forskellige testklasser, eller logikken, der skaber de nødvendige testdata, er så kompleks, at vi ikke ønsker at tilføje dem til vores testklasse, skal vi oprette en brugerdefineret ArgumentsProvider .
  • Hvis vi ønsker at levere vores testdata ved at bruge strenge og bruge metodeparametre, som ikke understøttes af standardargumentkonverteringerne, skal vi implementere en tilpasset ArgumentConverter .

No
Java tag