web-dev-qa-db-fra.com

Dans JUnit 5, comment exécuter du code avant tous les tests

Le @BeforeAll l'annotation marque une méthode à exécuter avant tous les tests dans une classe.

http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

Mais existe-t-il un moyen d'exécuter du code avant les tests all, dans toutes les classes?

Je veux m'assurer que les tests utilisent un certain ensemble de connexions à la base de données et que la configuration globale unique de ces connexions doit avoir lieu avant de s'exécuter tous les tests .

21
Rob N

Actuellement, cela n'est pas pris en charge, mais il existe une demande d'extraction pour JUnit 5 concernant ce sujet: Introduire la prise en charge des rappels avant/après une fois par cycle de test complet .

5
Stefan Birkner

Ceci est désormais possible dans JUnit5 en créant une extension personnalisée, à partir de laquelle vous pouvez enregistrer un hook d'arrêt sur le contexte de test racine.

Votre extension ressemblerait à ceci;

import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;

public class YourExtension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {

    private static boolean started = false;

    @Override
    public void beforeAll(ExtensionContext context) {
        if (!started) {
            started = true;
            // Your "before all tests" startup logic goes here
            // The following line registers a callback hook when the root test context is shut down
            context.getRoot().getStore(GLOBAL).put("any unique name", this);
        }
    }

    @Override
    public void close() {
        // Your "after all tests" logic goes here
    }
}

Ensuite, toutes les classes de tests dont vous avez besoin doivent être exécutées au moins une fois, peuvent être annotées avec:

@ExtendWith({YourExtension.class})

Lorsque vous utilisez cette extension sur plusieurs classes, la logique de démarrage et d'arrêt ne sera invoquée qu'une seule fois.

24
Philipp Gayret

Vous pouvez marquer chacune de vos classes de test qui utilise votre base de données avec une interface qui définit un staticBeforeAll (afin qu'il ne puisse pas être remplacé). par exemple.:

interface UsesDatabase {
    @BeforeAll
    static void initializeDatabaseConnections() {
        // initialize database connections
    }
}

Cette méthode sera invoquée une fois pour chaque classe d'implémentation, vous devrez donc définir un moyen d'initialiser vos connexions une seule fois, puis ne rien faire pour les autres appels.

3
mfulton26

Je ne connais aucun moyen de le faire.

Je voudrais simplement m'assurer que tout le code de @BeforeAll appelle un certain singleton pour faire fonctionner init (probablement de manière paresseuse pour éviter la répétition).

Probablement pas pratique ... la seule autre option que je vois: je suppose que vos tests s'exécutent dans un travail JVM spécifique. Vous pourriez accrocher un agent à cette exécution JVM, qui fait ce travail d'initialisation pour vous.

Au-delà de cela: les deux suggestions me semblent en quelque sorte un hack. La réponse réelle à mes yeux: reculez et examinez attentivement votre environnement sur ses dépendances. Et puis trouvez un moyen de préparer votre environnement de manière à ce que vos tests se présentent et que la "bonne chose" se produise automatiquement. En d'autres termes: envisagez d'examiner l'architecture qui vous a permis d'acquérir ce problème.

1
GhostCat

Les conseils ci-dessus font pas travailler pour moi, donc j'ai résolu ce problème comme ceci:

Ajoutez à votre classe abstraite de base (je veux dire la classe abstraite où vous initialisez votre pilote dans setUpDriver () méthode) cette partie du code:

private static boolean started = false;
static{
    if (!started) {
        started = true;
        try {
            setUpDriver();  //method where you initialize your driver
        } catch (MalformedURLException e) {
        }
    }
}

Et maintenant, si vos classes de test seront étend à partir de la classe abstraite de base -> la méthode setUpDriver () sera exécutée avant first @ Testez uniquement UNE fois par exécution du projet.

1
Sergii