Frage

Ich habe eine abstrakte Basisklasse, die ich als Basis für meine Unit -Tests verwende (TestNG 5.10). In dieser Klasse initialisiere ich die gesamte Umgebung für meine Tests, das Einrichten von Datenbankzuordnungen usw. Diese abstrakte Klasse hat eine Methode mit a @BeforeClass Annotation mit der Initialisierung.

Als nächstes erweitere ich diese Klasse mit bestimmten Klassen, in denen ich habe @Test Methoden und auch @BeforeClass Methoden. Diese Methoden führen die klassenspezifische Initialisierung der Umgebung durch (z. B. gibt einige Datensätze in die Datenbank).

Wie ich eine bestimmte Reihenfolge der durchsetzen kann @BeforeClass Annotierte Methoden? Ich brauche die aus der abstrakten Basisklasse, die vor denen der erweiterten Klasse ausgeführt werden können.

Beispiel:

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @BeforeClass
    doSpecificInitialization() {...}

    @Test
    doTests() {...}
}

Erwartete Reihenfolge:

A.doInitialization
B.doSpecificInitialization
B.doTests

Tatsächliche Reihenfolge:

B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization        // <---not executed
 B.doTests)                // <-/
War es hilfreich?

Lösung

Setzen Sie das nicht @BeforeClass auf der abstract Klasse. Nennen Sie es von jeder Unterklasse.

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

Scheint, als hätte Testng @BeforeClass(dependsOnMethods={"doInitialization"}) - Versuche es.

Andere Tipps

bearbeiten: Antwort unten ist für Jung, aber ich werde es sowieso hier lassen, weil es hilfreich sein könnte.

Laut dem JUNIT -API: "Die @BeForeClass -Methoden der Superklassen werden vor denen der aktuellen Klasse ausgeführt."

Ich habe das getestet und es scheint für mich zu funktionieren.

Wie @odys unten erwähnt, müssen Sie jedoch für Junit die haben zwei Methoden, die anders genannt werden Obwohl es nur zu der Ausführung der Subklassenmethode führt, weil das übergeordnete überschattet wird.

Ich fügte hinzu public an die abstrakte Klasse und testng (6.0.1) haben die DoInitialisierung () vor ausgeführt doTests. Testng wird nicht ausgeführt doInitialization() Wenn ich entferne public aus Klasse A.

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}

Ich habe gerade Ihr Beispiel mit 5.11 ausprobiert und erhalte den @BeForeclass der Basisklasse zuerst.

Können Sie Ihre testng.xml -Datei veröffentlichen? Vielleicht geben Sie dort sowohl A als auch B an, während nur B notwendig ist.

Fühlen Sie sich frei, die Versandliste der Testng-Benutzer nachzuverfolgen, und wir können uns Ihr Problem genauer ansehen.

- Cedric

Ich habe das gerade durchgemacht und noch einen Weg gefunden, dies zu erreichen. Benutz einfach alwaysRun an @BeforeClass oder @BeforeMethod In der abstrakten Klasse funktioniert, wie Sie es erwarten würden.

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}

Wenn ich aus: JUNITCORE.RUNCLASSS (TestClass.Class);Es wird den Elternteil vor dem Kind ordnungsgemäß ausführen (Sie brauchen nicht Super.setUpBeForeClass ();) Wenn Sie es aus Eclipse ausführen: Aus irgendeinem Grund kann es die Basisklasse nicht ausführen. Die Arbeit herum: Rufen Sie die Basisklasse explizit an: (BaSetest.setUpBeForeClass ();) Möglicherweise möchten Sie ein Flag in der Basisklasse haben, falls Sie es aus einer Anwendung ausführen, um festzustellen, ob es bereits eingerichtet ist oder nicht. Daher wird es nur einmal ausgeführt, wenn Sie es über mögliche Methoden ausführen (z.

Dies scheint ein Fehler mit Sonnenfinsternis oder zumindest unerwartete Ergebnisse zu sein.

Für jung: Wie @Fortega erwähnt hat: Laut der JUNIT -API: "Die @BeForeclass -Methoden der Superklassen werden vor denen der aktuellen Klasse ausgeführt."

Aber sei vorsichtig Nicht beide Methoden mit demselben Namen zu nennen. Da in diesem Fall die übergeordnete Methode von untergeordnetem Elternteil verborgen wird. Quelle.

Wie wäre es, wenn Ihre @BeForeClass -Methode eine leere methode spezifischbeForeclass () aufrufen kann, die durch Subklassen wie SO überschrieben werden kann oder nicht:

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}

dependsOnMethod kann verwendet werden.

zB im Fall des Frühlings (AbstractTestNGSpringContextTests)

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")

Überprüfen Sie Ihre Einfuhranweisung. Es sollte sein

import org.testng.annotations.BeforeClass;

nicht

import org.junit.BeforeClass;

Warum versuchen Sie nicht, in Ihrer Superklasse eine abstrakte Methode zu erstellen.

Entwicklungen, die Ihre Klasse erben, ist gezwungen, diese Methode zu implementieren.

Hier gibt es eine weitere einfache Lösung.

Meine besondere Situation ist, dass ich Scheindienste von "Beforeclass" in der Unterklasse vor "Bepereclass" in der Superklasse in die Unterklasse einbringen muss.

Dazu - verwenden Sie einfach a @ClassRule in der Unterklasse.

Zum Beispiel:

@ClassRule
public static ExternalResource mocksInjector = new ExternalResource() {
    @Override
    protected void before() {
        // inject my mock services here
        // Note: this is executed before the parent class @BeforeClass
    }
};

Ich hoffe das hilft. Dies kann in der Reihenfolge "Reverse" effektiv ein statisches Setup ausführen.

Ich habe heute einem ähnlichen Problem konfrontiert, der einzige Unterschied war, dass eine Basisklasse nicht abstrakt war

Hier ist mein Fall

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    private void doSpecificInitialization() {...}

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

Es kam vor, dass a @BeforeClass Die Methode aus der Klasse A wurde nie ausgeführt.

  • A.doinitialization () -> Dies wurde nie schweigend ausgeführt
  • B.dospecificinitialization ()
  • B.dotests ()

Spielen mit Datenschutzmodifikatoren Ich fand diesen Testng wird nicht ausführen a @BeforeClass Annotierte Methode aus ererbter Klasse Wenn eine Methode von einem Klassenunterherr nicht sichtbar ist

Das wird also funktionieren:

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
    protected void doSpecificInitialization() {...}

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

Infolgedessen kommt es zu:

  • A.doinitialization ()
  • B.dospecificinitialization ()
  • B.dotests ()

Das funktioniert für mich -

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}

In meinem Fall (jungit) habe ich die gleichen Methoden, die Setup () in der Basisklasse und in der abgeleiteten Klasse genannt werden. In diesem Fall nur Die Methode der abgeleiteten Klasse wird aufgerufen, und ich habe die Basisklassenmethode aufgerufen.

Eine bessere und sauberere Möglichkeit, dies mit der Vererbung zu erreichen, kann wie folgt sein -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top