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)                // <-/
Était-ce utile?

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

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 ..

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() {}
}
scroll top