J'ai une classe de base abstraite, que j'utilise comme base pour mes tests unitaires (TestNG 5.10). Dans cette classe, j'initialise l'environnement complet pour mes tests, la configuration de mappages de base de données, etc. Cette classe abstraite a une méthode avec une annotation @BeforeClass
qui effectue l'initialisation.
Ensuite, j'étend cette classe avec des classes spécifiques dans lesquelles j'ai des méthodes @Test
et également des méthodes @BeforeClass
. Ces méthodes effectuent l’initialisation de l’environnement spécifique à la classe (par exemple, placer des enregistrements dans la base de données).
Comment puis-je appliquer un ordre spécifique des méthodes annotées @BeforeClass
? J'ai besoin que ceux de la classe de base abstraite soient exécutés avant ceux de la classe d'extension.
Exemple:
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@BeforeClass
doSpecificInitialization() {...}
@Test
doTests() {...}
}
Commande attendue:
A.doInitialization
B.doSpecificInitialization
B.doTests
Ordre actuel:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
Ne mettez pas le @BeforeClass
sur la classe abstract
. Appelez-le 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"})
- l'essayer.
edit: La réponse ci-dessous est pour JUnit, mais je vais le laisser ici de toute façon, car cela pourrait être utile.
Selon le JUnit api : "Les méthodes des super-classes @BeforeClass seront exécutées avant celles de la classe actuelle."
J'ai testé cela et cela semble fonctionner pour moi.
Toutefois, comme @Odys le mentionne ci-dessous, pour JUnit, les méthodes two doivent être nommées différemment. Sinon, seule la méthode sous-classe sera exécutée, car le parent sera ombré.
J'ai ajouté public
à la classe abstraite et TestNG (6.0.1) a exécuté doInitialization () avant doTests
. TestNG n'exécute pas doInitialization()
si je supprime 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 j'obtiens d'abord le @BeforeClass de la classe de base.
Pouvez-vous poster votre fichier testng.xml? Peut-être que vous spécifiez à la fois A et B, alors que seul B est nécessaire.
N'hésitez pas à faire un suivi sur la liste de diffusion testng-users et nous pourrons examiner de plus près votre problème.
- Cédric
Je viens de traverser cela et j'ai trouvé un autre moyen d'y parvenir. Utilisez simplement alwaysRun
sur @BeforeClass
ou @BeforeMethod
dans la classe abstraite, fonctionne comme prévu.
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
Pour JUnit: Comme @fortega l'a mentionné: Selon l'API JUnit: "Les méthodes des superclasses @BeforeClass seront exécutées avant celles de la classe actuelle."
Mais faites attention ne pas nommer les deux méthodes avec le même nom}. Puisque dans ce cas, la méthode parent sera masquée par le parent parent. La source .
Quand je cours depuis: JUnitCore.runClasses (TestClass.class); Il exécutera correctement le parent avant l'enfant (Vous n'avez pas besoin de super.SetUpBeforeClass (); ) Si vous l'exécutez à partir d'Eclipse: exécutez la classe de base . Le travail autour de: Appelez explicitement la classe de base: ( BaseTest.setUpBeforeClass (); ) Vous souhaiterez peut-être avoir un indicateur dans la classe de base si vous l'exécutez à partir d'une application, afin de déterminer si elle est déjà configurée ou non. Ainsi, il ne s'exécute qu'une fois si vous l'exécutez via les deux méthodes possibles (par exemple, depuis Eclipse pour les tests personnels et via ANT pour une version de construction).
Cela semble être un bogue avec Eclipse, ou du moins des résultats inattendus.
Vérifiez votre déclaration d'importation . Elle devrait être
import org.testng.annotations.BeforeClass;
ne pas
import org.junit.BeforeClass;
dependsOnMethod
peut être utilisé.
par exemple. en cas de printemps (AbstractTestNGSpringContextTests
)
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
Pourquoi ne pas demander à votre méthode @BeforeClass d'appeler une méthode BeforeClass () spécifique vide qui peut ou non être écrasée par des sous-classes, 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
}
Cela fonctionne pour moi -
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
Il existe une autre solution facile ici.
Ma situation particulière est que je dois injecter des services factices à partir de "BeforeClass" dans la sous-classe avant que "BeforeClass" dans la superclasse soit exécuté.
Pour ce faire, utilisez simplement 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 ça aide. Cela peut effectivement exécuter la configuration statique dans l'ordre "inverse".
Pourquoi n'essayez-vous pas de créer une méthode abstraite doSpecialInit () dans votre super classe, appelée à partir de votre méthode annotée BeforeClass dans superclass.
Les développeurs qui héritent de votre classe doivent donc implémenter cette méthode.
J'ai rencontré un problème similaire aujourd'hui, la seule différence était qu'une classe de base n'était pas abstraite
Voici mon cas
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
Il s'est avéré qu'une méthode @BeforeClass
de la classe A n'a jamais été exécutée.
En jouant avec les modificateurs de confidentialité, j'ai constaté que TestNG n'exécutera pas une méthode annotée @BeforeClass
de la classe héritée si une méthode n'est pas visible depuis un héritier de la classe
Donc cela fonctionnera:
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 conséquence, il se produit ce qui suit: