Wie JUnit 4 parametriert Tests in JUnit 5 implementieren?

Schlitten:

In JUnit 4 war es leicht zu Test Invarianten über eine Reihe von Klassen durch die Verwendung der @ParameterizedAnnotation. Der Schlüssel ist , dass eine Sammlung von Tests gegen eine einzige Liste von Argumenten ausgeführt werden.

Wie dies in JUnit 5 replizieren, ohne JUnit-Jahrgang mit?

@ParameterizedTestist zu einer Testklasse nicht anwendbar. @TestTemplateklang wie es sinnvoll sein könnte, aber das Annotation des Ziel ist auch ein Verfahren.


Ein Beispiel eines solchen JUnit 4 Test ist:

@RunWith( Parameterized.class )
public class FooInvariantsTest{

   @Parameterized.Parameters
   public static Collection<Object[]> data(){
       return new Arrays.asList(
               new Object[]{ new CsvFoo() ),
               new Object[]{ new SqlFoo() ),
               new Object[]{ new XmlFoo() ),
           );
   }

   private Foo fooUnderTest;


   public FooInvariantsTest( Foo fooToTest ){
        fooUnderTest = fooToTest;
   }

   @Test
   public void testInvariant1(){
       ...
   }

   @Test
   public void testInvariant2(){
       ...
   } 
}
davidxxx:

Die parametrisierte Testfunktion in JUnit 5 bietet nicht exakt die gleichen Funktionen als die von JUnit 4 vorgesehen
Neue Funktionen mit mehr Flexibilität eingeführt wurden ... aber es auch die JUnit4 Funktion , wo die parametrisierte Testklasse verwendet die parametrisierte Stände / Behauptungen verloren auf Klassenebene , die für alle Prüfmethoden der Klasse ist.
Definieren @ParameterizedTestfür jedes Testverfahren durch die „Eingabe“ spezifiziert wird , so benötigt.
Darüber hinaus fehlt ich werde die wichtigsten Unterschiede zwischen den zwei Versionen präsentieren und wie 5 in JUnit parametrisierte Tests zu verwenden.

TL; DR

Um einen parametrisierte Test zu schreiben, der einen Wert von Fall zu testen , wie Ihre in Ihrer Frage gibt, org.junit.jupiter.params.provider.MethodSourcesoll die Arbeit machen.

@MethodSourcekönnen Sie eine oder mehrere Methoden der Testklasse verweisen. Jede Methode muss wieder ein Stream, Iterable, Iterator, oder ein Array von Argumenten. Darüber hinaus muss jede Methode keine Argumente akzeptieren. Standardmäßig müssen solche Methoden statisch sein , wenn die Testklasse wird mit Anmerkungen versehen mit @TestInstance(Lifecycle.PER_CLASS).

Wenn Sie nur einen einzigen Parameter benötigen, können Sie Instanzen des Parameters Typ zurückgeben direkt wie das folgende Beispiel demonstriert.

Wie JUnit 4, @MethodSourceberuht auf einem Fabrikmethode als auch für Testverfahren verwendet werden kann , die mehrere Argumente angeben.

In JUnit 5 ist es die Art und Weise parametriert Tests des Schreibens in der Nähe von JUnit 4.

JUnit 4:

@Parameters
public static Collection<Object[]> data() {

JUnit 5:

private static Stream<Arguments> data() {

Die wichtigsten Verbesserungen:

  • Collection<Object[]>geworden ist , Stream<Arguments>dass mehr Flexibilität bietet.

  • die Möglichkeit , die Factory - Methode der Testmethode der Bindung unterscheidet sich ein wenig.
    Es ist jetzt kürzer und weniger fehleranfällig: nicht mehr Anforderung einen Konstruktor zu erstellen und erklärt Feld den Wert der einzelnen Parameter einzustellen. Die Bindung der Quelle erfolgt direkt auf die Parameter des Testverfahrens.

  • Mit JUnit 4, in einer gleichen Klasse, ein und nur ein Factory - Methode muss mit erklärt @Parameters.
    Mit JUnit 5 wird diese Einschränkung aufgehoben: mehrere Methoden in der Tat als Factory - Methode verwendet werden.
    Also, in der Klasse, können wir so einige Testmethoden mit kommentierten erklären , @MethodSource("..")dass siehe Methoden unterschiedliche Fabrik.

Zum Beispiel ist hier eine Probe-Test-Klasse, die einige zusätzlich Berechnungen behauptet:

import java.util.stream.Stream;

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

public class ParameterizedMethodSourceWithArgumentsTest {

  @ParameterizedTest
  @MethodSource("addFixture")
  void add(int a, int b, int result) {
     Assertions.assertEquals(result, a + b);
  }

  private static Stream<Arguments> addFixture() {
    return Stream.of(
      Arguments.of(1, 2, 3),
      Arguments.of(4, -4, 0),
      Arguments.of(-3, -3, -6));
  }
}

Um ein Upgrade bestehende parametrisiert Tests von JUnit 4 bis JUnit 5, @MethodSourceist ein Kandidat zu betrachten.


Zusammenfassen

@MethodSourceeinige Stärken hat aber auch einige Schwächen.
Neue Wege Quellen der parametrisierte Tests wurden eingeführt in JUnit 5. angeben
Hier einige zusätzliche Informationen (weit abschließend ist) über ihnen , dass ich hoffe , eine große Idee, wie viel mit in allgemeiner Art und Weise geben könnte.

Einführung

JUnit 5 führt parametrisiert Tests verfügen in diesen Begriffen:

Parameterized Tests machen es möglich , einen Test mehrmals mit verschiedenen Argumenten zu laufen. Sie werden wie normale erklärt @TestMethoden , sondern verwenden Sie die @ParameterizedTestAnmerkung statt. Darüber hinaus müssen Sie mindestens eine Quelle angeben, die die Argumente für jeden Aufruf zur Verfügung stellen.

Dependency Anforderung

Parameterized Tests Funktion ist in der nicht enthält junit-jupiter-engineKern Abhängigkeit.
Sie sollten eine spezifische Abhängigkeit hinzufügen , es zu benutzen: junit-jupiter-params.

Wenn Sie Maven verwenden, ist dies die Abhängigkeit zu erklären:

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

Quellen zur Verfügung, um Daten zu erstellen

Im Gegensatz zu JUnit 4, JUnit 5 bietet mehrere Aromen und Artefakte zu parametrieren Tests schreiben
die Wege zu Gunsten hängen in der Regel von der Quelle der Daten , die Sie verwenden möchten.

Hier sind die Quellentypen von Rahmen vorgeschlagen und in der beschriebenen Dokumentation :

  • @ValueSource
  • @EnumSource
  • @MethodSource
  • @CsvSource
  • @CsvFileSource
  • @ArgumentsSource

Hier sind die 3 wichtigsten Quellen, die ich eigentlich mit JUnit verwenden 5 und ich präsentieren:

  • @MethodSource
  • @ValueSource
  • @CsvSource

Ich betrachte sie als Grund wie ich parametrisierte Tests schreiben. Sie sollten in JUnit 5, die Art von 4 Tests JUnit schreiben lassen , dass Sie beschrieben.
@EnumSource, @ArgumentsSourceUnd @CsvFileSourceseine natürlich hilfreich sein , aber sie sind mehr spezialisiert.

Präsentation @MethodSource, @ValueSourceund@CsvSource

1) @MethodSource

Diese Art der Quelle erfordert eine Factory - Methode zu definieren.
Aber es gibt auch viel Flexibilität.

In JUnit 5 ist es die Art und Weise parametriert Tests des Schreibens in der Nähe von JUnit 4.

Wenn Sie einen haben einzelne Methode Parameter in der Testmethode und die Sie verwenden möchten , jede Art als Quelle, @MethodSourceist ein sehr guter Kandidat.
Um dies zu erreichen, definiert ein Verfahren , welches Returns einen Strom von dem Wert für jeden Fall und mit Anmerkungen versehen , die Testmethode mit @MethodSource("methodName")dem methodNameist der Name dieser Datenquelle Methode.

Zum Beispiel könnten Sie schreiben:

import java.util.stream.Stream;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class ParameterizedMethodSourceTest {

    @ParameterizedTest
    @MethodSource("getValue_is_never_null_fixture")
    void getValue_is_never_null(Foo foo) {
       Assertions.assertNotNull(foo.getValue());
    }

    private static Stream<Foo> getValue_is_never_null_fixture() {
       return Stream.of(new CsvFoo(), new SqlFoo(), new XmlFoo());
    }

}

Wenn Sie mehrere Verfahrensparameter in der Testmethode und die Sie verwenden möchten , jede Art als Quelle, @MethodSourceist auch ein sehr guter Kandidat.
Um dies zu erreichen, definiert ein Verfahren , das einen Strom von kehrt org.junit.jupiter.params.provider.Argumentsfür jeden Fall zu prüfen.

Zum Beispiel könnten Sie schreiben:

import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;    
import org.junit.jupiter.api.Assertions;

public class ParameterizedMethodSourceWithArgumentsTest {

    @ParameterizedTest
    @MethodSource("getFormatFixture")
    void getFormat(Foo foo, String extension) {
        Assertions.assertEquals(extension, foo.getExtension());
    }

    private static Stream<Arguments> getFormatFixture() {
    return Stream.of(
        Arguments.of(new SqlFoo(), ".sql"),
        Arguments.of(new CsvFoo(), ".csv"),
        Arguments.of(new XmlFoo(), ".xml"));
    }
}

2)@ValueSource

Wenn Sie einen haben einzelne Methode Parameter in der Testmethode und Sie können die Quelle des Parameters von repräsentieren eine dieser integrierten Typen (String, int, long, double) , @ValueSourceAnzüge.

@ValueSource definiert, in der Tat diese Attribute:

String[] strings() default {};
int[] ints() default {};
long[] longs() default {};
double[] doubles() default {};

Sie könnten zum Beispiel auf diese Weise verwenden:

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

public class ParameterizedValueSourceTest {

    @ParameterizedTest
    @ValueSource(ints = { 1, 2, 3 })
    void sillyTestWithValueSource(int argument) {
        Assertions.assertNotNull(argument);
    }

}

Beware 1) nicht mehr als eine Anmerkung Attribut angeben müssen.
Vorsicht vor 2) die Zuordnung zwischen der Quelle und dem Parameter des Verfahrens kann zwischen zwei verschiedenen Arten erfolgen.
Die Art Stringals Datenquelle verwendet wird, erlaubt besonders dank seiner Analyse, in mehrere andere Typen umgewandelt werden.

3) @CsvSource

Wenn Sie mehrere Verfahrensparameter in dem Testverfahren, ein @CsvSourceAnzug kann.
Um sie zu verwenden, den Test mit Anmerkungen versehen @CsvSourceund in einem Array von spezifizieren Stringjeweils.
Werte von jeweils durch ein Komma getrennt.

Wie @ValueSourceich die Abbildung zwischen der Quelle und dem Parameter des Verfahrens kann zwischen zwei verschiedenen Arten erfolgen.
Hier ist ein Beispiel, das veranschaulicht:

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

public class ParameterizedCsvSourceTest {

    @ParameterizedTest
    @CsvSource({ "12,3,4", "12,2,6" })
    public void divideTest(int n, int d, int q) {
       Assertions.assertEquals(q, n / d);
    }

}

@CsvSource VS @MethodSource

Diese Quellentypen dienen eine sehr klassische Anforderung: Abbilden von der Quelle zu mehreren Verfahrensparametern in der Testmethode.
Aber ihr Ansatz ist anders.

@CsvSourcehat einige Vorteile: es klarer und kürzer ist.
Tatsächlich sind Parameter definiert knapp über der getestete Methode, keine Anforderung einer Befestigung Methode zu erstellen , die Warnungen zusätzlich generieren „ungenutzt“ kann.
Aber es hat auch eine wichtige Einschränkung Mapping - Arten betreffen.
Sie haben eine Reihe von zur Verfügung zu stellen String. Das Framework bietet Konvertierungsfunktionen , aber es ist begrenzt.

Zusammenfassend , während die Stringals Quelle zur Verfügung gestellt und die Parameter des Testverfahrens haben den gleichen Typ ( String-> String) oder sich auf integrierte Umwandlung in ( String-> intzum Beispiel), @CsvSourcewird als die Weise zu nutzen.

Da es nicht der Fall ist, müssen Sie zwischen Beibehaltung der Flexibilität des eine Wahl treffen , @CsvSourceindem Sie einen benutzerdefinierten Wandler ( ArgumentConverterUnterklasse) für Konvertierungen nicht durchgeführt durch den Rahmen oder unter Verwendung von @MethodSourcemit einer Factory - Methode , dass die Renditen Stream<Arguments>.
Es hat die beschriebenen Nachteile oben , aber es hat auch den großen Vorteil abzubilden out-of-the - Box jede Art von der Quelle auf die Parameter.

Argument Conversion

Über die Zuordnung zwischen der Quelle ( @CsvSourceoder @ValueSourcezum Beispiel) und die Parameter des Testverfahrens, wie es zu sehen ist , kann der Rahmen einige Umwandlungen tun , wenn die Typen nicht übereinstimmen.

Hier ist eine Präsentation der zwei Arten von Umwandlungen:

3.13.3. Argument Conversion

implizite Konvertierung

Um Anwendungsfälle wie zu unterstützen @CsvSource, JUnit Jupiter bietet eine Reihe von integrierten in impliziten Typ - Wandler. Der Umwandlungsprozess hängt von dem deklarierten Typ jeden Verfahrensparameters.

.....

String Instanzen derzeit auf die folgenden Zieltypen implizit konvertiert.

Target Type          |  Example
boolean/Boolean      |  "true" → true
byte/Byte            |  "1" → (byte) 1
char/Character       |  "o" → 'o'
short/Short          |  "1" → (short) 1
int/Integer          |  "1" → 1
.....

Zum Beispiel in dem vorherigen Beispiel wird eine implizite Konvertierung zwischen getan Stringvon der Quelle und intals Parameter definiert ist :

@CsvSource({ "12,3,4", "12,2,6" })
public void divideTest(int n, int d, int q) {
   Assertions.assertEquals(q, n / d);
}

Und hier ist eine implizite Konvertierung von getan StringQuelle LocalDateParameter:

@ParameterizedTest
@ValueSource(strings = { "2018-01-01", "2018-02-01", "2018-03-01" })
void testWithValueSource(LocalDate date) {
    Assertions.assertTrue(date.getYear() == 2018);
}

Wenn für zwei Typen, keine Konvertierung von Rahmen vorgesehen ist, die der Fall für benutzerdefinierte Typen ist, sollten Sie eine verwenden ArgumentConverter.

explizite Konvertierung

Stattdessen implizites Argument Umwandlung verwenden , können Sie explizit eine angeben ArgumentConverterfür einen bestimmten Parameter verwenden , um die Verwendung von @ConvertWithAnnotations wie im folgende Beispiel.

JUnit bietet eine Referenzimplementierung für Kunden , die eine bestimmte erstellen müssen ArgumentConverter.

Explizite Argument Wandler sollen durch Test Autoren umgesetzt werden. So junit-jupiter-params liefert nur einen einzigen expliziten Argument Konverter, der auch als Referenz - Implementierung dienen können: JavaTimeArgumentConverter. Sie wird über die zusammengesetzte Anmerkung verwendet JavaTimeConversionPattern.

Testverfahren unter Verwendung dieser Konverter:

@ParameterizedTest
@ValueSource(strings = { "01.01.2017", "31.12.2017" })
void testWithExplicitJavaTimeConverter(@JavaTimeConversionPattern("dd.MM.yyyy") LocalDate argument) {
    assertEquals(2017, argument.getYear());
}

JavaTimeArgumentConverter Konverterklasse:

package org.junit.jupiter.params.converter;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.ChronoZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalQuery;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

import org.junit.jupiter.params.support.AnnotationConsumer;

/**
 * @since 5.0
 */
class JavaTimeArgumentConverter extends SimpleArgumentConverter
        implements AnnotationConsumer<JavaTimeConversionPattern> {

    private static final Map<Class<?>, TemporalQuery<?>> TEMPORAL_QUERIES;
    static {
        Map<Class<?>, TemporalQuery<?>> queries = new LinkedHashMap<>();
        queries.put(ChronoLocalDate.class, ChronoLocalDate::from);
        queries.put(ChronoLocalDateTime.class, ChronoLocalDateTime::from);
        queries.put(ChronoZonedDateTime.class, ChronoZonedDateTime::from);
        queries.put(LocalDate.class, LocalDate::from);
        queries.put(LocalDateTime.class, LocalDateTime::from);
        queries.put(LocalTime.class, LocalTime::from);
        queries.put(OffsetDateTime.class, OffsetDateTime::from);
        queries.put(OffsetTime.class, OffsetTime::from);
        queries.put(Year.class, Year::from);
        queries.put(YearMonth.class, YearMonth::from);
        queries.put(ZonedDateTime.class, ZonedDateTime::from);
        TEMPORAL_QUERIES = Collections.unmodifiableMap(queries);
    }

    private String pattern;

    @Override
    public void accept(JavaTimeConversionPattern annotation) {
        pattern = annotation.value();
    }

    @Override
    public Object convert(Object input, Class<?> targetClass) throws ArgumentConversionException {
        if (!TEMPORAL_QUERIES.containsKey(targetClass)) {
            throw new ArgumentConversionException("Cannot convert to " + targetClass.getName() + ": " + input);
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        TemporalQuery<?> temporalQuery = TEMPORAL_QUERIES.get(targetClass);
        return formatter.parse(input.toString(), temporalQuery);
    }

}

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

Parametriert vor jedem / vor allen in JUnit 5

Wie man JUnit Jupiter @MethodSource Wiederverwendung für mehrere Tests parametriert

JUnit Parametriert mit einer großen Anzahl von Tests

Wie sind Dynamische von Parameterized Tests in JUnit 5 verschiedene Tests?

JUnit 4: Verschachtelte Tests

Tests unter JUnit 4 laufen, aber nicht JUnit 5 - Kompiliert sauber, aber 0 Tests ausführen

Wie erhalte ich die aktuelle Wiederholungszahl des Tests in JUnit 5?

Wie WireMock Antwortvorlage in JUnit 5 Tests zu verwenden,

Wie JUnit5 Tests auf Klassenstufe wiederholen?

JUnit 4 - Wie ignoriere ich alle Pakete mit den Tests?

JUnit 5 - Parametrisierte verschachtelte Tests

Junit 5 benutzerdefinierte parametrisierte Tests

Tests in JUnit 4 bedingt ignorieren

JUnit4- und JUnit5-Tests werden in IntelliJ nicht ausgeführt

Warum bestehende Tests von JUnit4 auf Junit5 umstellen?

Migrationsproblem von Junit 4 zu Junit 5

Wie JUnit 5 und JUnit 4 Test-Suiten in Gradle laufen?

Wie parametriere beforeEach () in JUnit 5?

Wie schreibe ich JUnit-Tests?

JUnit: Wie simuliere ich System.in-Tests?

Junit Parametrisierte Tests zusammen mit Powermock - wie?

Verständnis Ausnahme Tests in JUnit 5

So bestellen Sie Tests mit junit 5

Parametrisieren sowohl Klasse und Tests in JUnit 5

Gradle Projektlauf jUnit 5 Tests in IntelliJ

JUnit5-Assertionszählung in Tests

JUnit4 - AssertionFailedError: Keine Tests gefunden

So implementieren Sie einen benutzerdefinierten Runner in JUnit5

Wie aktualisiere ich mit @RunWith (classOf [JUnitRunner]) auf JUnit5 für Scala-Tests?

TOP Liste

  1. 1

    So legen Sie mit dem Interface Builder unterschiedliche führende Speicherplätze für unterschiedliche Geräte fest

  2. 2

    Fügen Sie eine weitere Schaltfläche zu gwt Suggest Box hinzu

  3. 3

    Wie konvertiere ich einen Vektor von Bytes (u8) in eine Zeichenfolge?

  4. 4

    Wie kann ich in SCSS mehrere Klassen zu einer einzigen kombinieren?

  5. 5

    Wie konvertiert man einen Datenrahmen im langen Format in eine Liste mit einem geeigneten Format?

  6. 6

    Speichern Sie ein MPAndroidChart-Diagramm in einem Bild, ohne es in einer Aktivität anzuzeigen

  7. 7

    Gruppieren Sie Datenrahmenspalten nach ihrem Datum (die Spaltentitel enthalten) und fassen Sie die Instanzen von Einsen und Nullen in R . zusammen

  8. 8

    Tomcat - Leiten Sie den alten Kontextstamm zum neuen Kontextstamm um

  9. 9

    Eclipse Oxygen - Projekte verschwinden

  10. 10

    Wie wählt man Unterschiede mit drei Tabellen aus?

  11. 11

    Tic Tac Toe-Spiel im React-Reset-Button funktioniert nicht

  12. 12

    So berechnen Sie die Verfügbarkeit von Anwendungen (SLA)

  13. 13

    ElasticSearch BulkShardRequest ist aufgrund von org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor fehlgeschlagen

  14. 14

    Wie kann ich den Kaskadenmodus global einstellen?

  15. 15

    Python: Spalten mit demselben Namen zusammenführen, wobei der Mindestwert beibehalten wird

  16. 16

    So erhalten Sie eine gleichmäßige Höhe für alle Eingabefelder

  17. 17

    Wie erstelle ich einen neuen übergeordneten Knoten außerhalb der .ref (/ path) in der Firebase-Echtzeitdatenbank mithilfe von Cloud-Funktionen (Typescript)?

  18. 18

    Was ist schneller: SUM über NULL oder über 0?

  19. 19

    Wie kann ich eine verschachtelte Schleife mit lapply in R ersetzen?

  20. 20

    Kann ich ein Tkinter-Canvas erstellen, das mehrere Zeilen in einem Text-Widget umfasst?

  21. 21

    Ärgerliches Problem mit yaml, das ich nicht lösen kann

heißlabel

Archiv