@BeForeclass und Erbschaft - Reihenfolge der Ausführung
-
22-09-2019 - |
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) // <-/
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() {}
}