Welchen Nutzen hat die Annotation @TestInstance in JUnit 5?

Lesezeit: 5 Minuten

Benutzeravatar von Mahozad
Mahozad

Können Sie eine einfache Erklärung geben @TestInstance Anmerkung und wie ist sie in JUnit 5 nützlich?

Ich denke, wir können den gleichen Effekt wahrscheinlich dadurch erzielen unsere Felder machen static.

Benutzeravatar von glytching
glitzern

Ich finde die Dokumente geben Sie eine nützliche Zusammenfassung:

Wenn Sie möchten, dass JUnit Jupiter alle Testmethoden auf derselben Testinstanz ausführt, versehen Sie Ihre Testklasse einfach mit @TestInstance(Lifecycle.PER_CLASS). Bei Verwendung dieses Modus wird einmal pro Testklasse eine neue Testinstanz erstellt. Wenn Ihre Testmethoden also auf in Instanzvariablen gespeicherte Zustände angewiesen sind, müssen Sie diesen Zustand möglicherweise in @BeforeEach- oder @AfterEach-Methoden zurücksetzen.

Der „Pro-Klassen“-Modus hat einige zusätzliche Vorteile gegenüber dem standardmäßigen „Pro-Methoden“-Modus. Insbesondere mit dem Modus „pro Klasse“ wird es möglich, @BeforeAll und @AfterAll sowohl für nicht statische Methoden als auch für Schnittstellen-Standardmethoden zu deklarieren. Der Modus “pro Klasse” ermöglicht es daher auch, @BeforeAll- und @AfterAll-Methoden in @Nested-Testklassen zu verwenden.

Aber Sie haben das wahrscheinlich schon gelesen und Sie haben Recht mit der Annahme, dass das Festlegen eines statischen Felds denselben Effekt hat wie das Deklarieren des Felds als Instanzvariable und Verwenden @TestInstance(Lifecycle.PER_CLASS).

Vielleicht lautet die Antwort auf die Frage „wie es in JUnit 5 nützlich sein könnte“, dass die Verwendung von a @TestInstance

  • Ist ausdrücklich über Ihre Absichten. Es könnte davon ausgegangen werden, dass die Verwendung des statischen Schlüsselworts zufällig war, während die Verwendung von @TestInstance ist weniger wahrscheinlich zufällig oder das Ergebnis von gedankenlosem Kopieren und Einfügen.
  • Delegiert die Verantwortung für die Verwaltung von Umfang und Lebenszyklus und die Bereinigung des Frameworks, anstatt daran denken zu müssen, dies selbst zu verwalten.

  • Es ist auch eine Voraussetzung, wenn Sie parametrisierte Tests mit MethodSource in verschachtelten Testklassen erstellen möchten github.com/junit-team/junit5/issues/1229

    – Nitesh

    26. September 2019 um 12:01 Uhr


  • Testklassenmitglieder statisch zu machen, kann bei Klassenhierarchien problematisch sein. Polymorphismus bietet Ihnen einige coole Optionen, um saubereren und weniger redundanten Code zu schreiben. @TestInstance(PER_CLASS) sollte die Standardeinstellung in Jupiter IMHO sein. Es führt zu besserem und elastischerem Testcode und hat gegenüber der Alternative nur Vorteile.

    – Janni

    23. August 2020 um 9:54 Uhr


Diese Anmerkung wurde eingeführt, um die Anzahl der Objekte zu reduzieren, die beim Ausführen Ihrer Komponententests erstellt werden.

Hinzufügen @TestInstance(TestInstance.Lifecycle.PER_CLASS) zu Ihrer Testklasse wird vermeiden, dass für jeden Test in der Klasse eine neue Instanz Ihrer Klasse erstellt wird. Dies ist besonders nützlich, wenn Sie viele Tests in derselben Testklasse haben und die Instanziierung dieser Klasse teuer ist.

Diese Anmerkung sollte mit Vorsicht verwendet werden. Alle Unit-Tests sollten isoliert und unabhängig voneinander durchgeführt werden. Wenn einer der Tests den Status der Testklasse ändert, sollten Sie diese Funktion nicht verwenden.

Es ist keine gute Idee, Ihre Felder statisch zu machen, um den gleichen Effekt zu erzielen. Es wird zwar die Anzahl der erstellten Objekte reduzieren, aber sie können nicht bereinigt werden, wenn alle Tests in der Testklasse ausgeführt werden. Dies kann Probleme verursachen, wenn Sie eine riesige Testsuite haben.

  • Ich mag diese Antwort, weil sie direkt einen großen Nachteil der Verwendung statischer Felder anspricht.

    – Nathan Hughes

    28. September 2018 um 12:07 Uhr

  • @dyVeloper Was wird die ähnliche Anmerkung in testng sein?

    – gomathi subramanian

    12. September um 7:46 Uhr


Benutzeravatar von cassiomolin
Cassiomolin

@TestInstance wird verwendet, um die zu konfigurieren Lebenszyklus von Testinstanzen für die annotierte Testklasse oder Testschnittstelle:

  • PER_CLASS: Pro Testklasse wird einmal eine neue Testinstanz erstellt.
  • PER_METHOD: Für jede Testmethode, Test-Factory-Methode oder Testvorlagenmethode wird eine neue Testinstanz erstellt. Dieser Modus entspricht dem Verhalten der JUnit-Versionen 1 bis 4.

Wenn @TestInstance nicht explizit für eine Testklasse oder eine von einer Testklasse implementierte Testschnittstelle deklariert wird, wird der Lebenszyklusmodus implizit standardmäßig verwendet PER_METHOD.


Festlegen des Lebenszyklusmodus der Testinstanz auf PER_CLASS aktiviert die folgenden Funktionen:

  • Gemeinsamer Testinstanzzustand zwischen Testmethoden in einer bestimmten Testklasse sowie zwischen nicht statischen @BeforeAll und @AfterAll Methoden in der Testklasse.
  • Erklärung von @BeforeAll und @AfterAll Methoden ein @Nested Testklassen.
  • Erklärung von @BeforeAll und @AfterAll auf Schnittstellen-Standardmethoden.
  • Vereinfachte Deklaration von @BeforeAll und @AfterAll Methoden in Testklassen, die mit der Programmiersprache Kotlin implementiert wurden.

Siehe die Testinstanz-Lebenszyklus Dokumentation für weitere Details.

Da niemand ein richtiges Codierungsbeispiel bereitstellt, möchte ich unten ein einfaches Codebeispiel geben, um das Konzept zu verstehen.

Beispiel pro Methode – Standardoption in Junit5
Beachten Sie, dass zwei Methoden statisch sind. Andernfalls wird eine Ausnahme ausgelöst, da die Klasse in jeder Methode instanziiert wird.

@TestInstance(Lifecycle.PER_METHOD)
public class MathUtilTestPerMethod {

    MathUtil util;

    @BeforeAll
    static void beforeAllInit() {
        System.out.println("running before all");
    }

    @AfterAll
    static void afterAllCleanUp() {
        System.out.println("running after all");
    }

    @BeforeEach
    void init() {
        util = new MathUtil();
        System.out.println("running before each...");
    }

    @AfterEach
    void cleanUp() {
        System.out.println("running after each...");
    }

    @Test
    void testSum() {
        assertEquals(2, util.addtwoNumbers(1, 1));
    }

}

Probe pro Klasse
Beachten Sie, dass static aus den beiden Methoden entfernt wird und das MathUtil-Objekt global und nicht in einer Methode erstellt wird, da die Klasse nur einmal instanziiert wird.

@TestInstance(Lifecycle.PER_CLASS)
public class MathUtilTestPerClass {

    MathUtil util = new MathUtil();

    @BeforeAll
    void beforeAllInit() {
        System.out.println("running before all");
    }

    @AfterAll
    void afterAllCleanUp() {
        System.out.println("running after all");
    }

    @BeforeEach
    void init() {
        System.out.println("running before each...");
    }

    @AfterEach
    void cleanUp() {
        System.out.println("running after each...");
    }

    @Test
    void testSum() {
        assertEquals(2, util.addtwoNumbers(1, 1));
    }

}

Benutzeravatar von Mahozad
Mahozad

Dies ist auch beim Schreiben von Tests nützlich Kotlin (weil es keine statischen Methoden hat).

Anstatt also ein Begleitobjekt mit zu verwenden @JvmStatic Spaß daran @BeforeAll oder @AfterAllmachen den Lebenszyklus PER_CLASS und kommentieren Sie reguläre Methoden mit @BeforeAll oder @AfterAll:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {

    @BeforeAll
    fun setup() {
        println("I am invoked only once")
    }
}

Wenn Sie diesen Ansatz verwenden, achten Sie darauf, Ihre Instanzvariablen in zurückzusetzen @BeforeEach oder @AfterEach Spaß, wenn nötig.

Dank an Dieser Artikel für seine Hilfe.

1435960cookie-checkWelchen Nutzen hat die Annotation @TestInstance in JUnit 5?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy