@BeforeClass et héritage - ordre d'exécution
-
22-09-2019 - |
Question
J'ai une classe de base abstraite, que je l'utilise comme base pour mes tests unitaires (TestNG 5,10). Dans cette classe, j'initialiser tout l'environnement pour mes tests, la mise en place de bases de données cartographies, etc. Cette classe abstraite a une méthode avec une annotation @BeforeClass
qui fait l'initialisation.
Ensuite, j'étendre cette classe avec des classes spécifiques où j'ai des méthodes de @Test
et aussi des méthodes @BeforeClass
. Ces méthodes font l'initialisation spécifique à la classe de l'environnement (par exemple mettre des enregistrements dans la base de données).
Comment puis-je appliquer un ordre spécifique des méthodes de @BeforeClass
annotée? J'ai besoin ceux de la classe de base abstraite à exécuter avant ceux de la classe extension.
Exemple:
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@BeforeClass
doSpecificInitialization() {...}
@Test
doTests() {...}
}
ordre attendu:
A.doInitialization
B.doSpecificInitialization
B.doTests
ordre réel:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
La solution
Ne pas mettre la @BeforeClass
sur la classe abstract
. Appelez-de chaque sous-classe.
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
On dirait que TestNG a @BeforeClass(dependsOnMethods={"doInitialization"})
- essayer.
Autres conseils
modifier. Réponse ci-dessous est JUnit , mais je laisse ici de toute façon, car il pourrait être utile
Selon le : « Les @BeforeClass méthodes de superclasses seront exécutés avant ceux de la classe actuelle. "
Je l'ai testé cela, et il semble fonctionner pour moi.
Cependant, comme @Odys mentionne ci-dessous, pour JUnit vous devez avoir les deux méthodes nommées différemment mais que faire autrement entraînera seulement la méthode de la sous-classe en cours d'exécution parce que le parent sera occulté.
J'ai ajouté public
à la classe abstraite et TestNG (6.0.1) a exécuté le doInitialization () avant doTests
. TestNG n'exécute pas doInitialization()
si je retire public
de la classe A.
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
Je viens d'essayer votre exemple avec 5.11 et je reçois le @BeforeClass de la classe de base invoqué en premier.
Pouvez-vous envoyer votre fichier testng.xml? Peut-être que vous spécifiez A et B là, tandis que B est nécessaire.
Ne hésitez pas à donner suite aux utilisateurs de TestNG-liste de diffusion et nous pouvons regarder de plus près à votre problème.
- Cedric
Je viens juste de passer à travers cela et trouvé un autre moyen d'y parvenir. Il suffit d'utiliser alwaysRun
sur @BeforeClass
ou @BeforeMethod
dans la classe abstraite, les travaux que vous attendez.
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
Quand je cours à partir de: JUnitCore.runClasses (TestClass.class); Il exécutera le parent correctement, avant que l'enfant (Vous n'avez pas besoin super.SetUpBeforeClass (); ) Si vous exécutez d'Eclipse: Pour une raison quelconque, il ne parvient pas à exécuter la classe de base. Le travail autour de: Appelez la classe de base explicite: ( BaseTest.setUpBeforeClass (); ) Vous voudrez peut-être avoir un drapeau dans la classe de base au cas où vous l'exécutez d'une application, pour déterminer si elle est déjà configuré ou non. Donc, il fonctionne qu'une seule fois si vous l'exécutez via les deux méthodes possibles (par exemple de l'éclipse pour les tests personnels, et par ANT pour une version de construction).
Cela semble être un bug avec Eclipse, ou les résultats inattendus au moins ..
Pour JUnit : Comme @fortega a mentionné: Selon le api JUnit: «Les méthodes @BeforeClass de superclasses seront exécutés avant ceux de la classe actuelle »
Mais attention ne pas nommer les deux méthodes avec le même nom . Etant donné que dans ce cas, la méthode parent sera caché par le parent de l'enfant. source.
Que diriez-vous d'avoir votre méthode méthode @BeforeClass appeler un specificBeforeClass () vide qui peuvent ou peuvent ne pas être écrasé par des sous catégories comme ceci:
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
peut être utilisé.
par exemple. en cas de ressort (AbstractTestNGSpringContextTests
)
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
Vérifiez votre relevé d'importation. Il devrait être
import org.testng.annotations.BeforeClass;
pas
import org.junit.BeforeClass;
Pourquoi ne pas essayer de créer une méthode abstraite doSpecialInit () dans votre super classe, appelée à partir de votre BeforeClass méthode annoté superclasse.
developpeurs héritant votre classe est obligé de mettre en œuvre cette méthode.
Il y a une autre solution facile ici.
Ma situation est que je dois injecter des services simulacres de « BeforeClass » dans la sous-classe avant « BeforeClass » dans la superclasse est exécutée.
Pour ce faire - il suffit d'utiliser un @ClassRule
dans la sous-classe
Par exemple:
@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
}
};
J'espère que cela aide. Cela peut exécuter efficacement la configuration statique dans l'ordre « inverse ».
Je suis face à un problème similaire aujourd'hui, la seule différence était une classe de base n'a pas été abstraite
Voilà mon cas
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
Il est apparu que une méthode de @BeforeClass
de la classe A n'a jamais été exécuté.
- A.doInitialization () -> CE n'a jamais été exécuté en silence
- B.doSpecificInitialization ()
- B.doTests ()
Jouer avec des modificateurs de la vie privée, je trouve que TestNG n'exécutera une méthode annotée de @BeforeClass
de classe héritée si une méthode n'est pas visible d'une classe-Héritier
Alors que cela fonctionne:
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() {...}
}
En résultat suivant se produit:
- A.doInitialization ()
- B.doSpecificInitialization ()
- B.doTests ()
Cela fonctionne pour moi -
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
Dans mon cas (JUnit) j'ai les mêmes méthodes appelées setup () dans la classe de base et la classe dérivée. Dans ce cas, uniquement méthode de la classe dérivée est appelée, et je l'ai appeler la méthode de classe de base.
Une meilleure et plus propre moyen de parvenir à cet héritage en utilisant peut-être comme suit -
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}