Junit4: La méthode @Parameters est exécutée avant l'initialisation de @ClassRule. Pourrait-il être le chemin autour?

Créé le 2 mai 2013  ·  9Commentaires  ·  Source: junit-team/junit4

J'ai le problème suivant (en utilisant _junit 4.11_):

    <strong i="6">@ClassRule</strong>
    public static TemporaryFolder tmp = new TemporaryFolder();
    ...
    <strong i="7">@Parameters</strong>
    public static Collection<Object[]> data() throws Exception {
        return java.util.Arrays.asList(new Object[][] {
            {0, tmp.getRoot().getPath()}
        });
    }

Cela se traduit par une erreur d' initialisation

java.lang.IllegalStateException: the temporary folder has not yet been created
    at org.junit.rules.TemporaryFolder.getRoot(TemporaryFolder.java:127)

Il semble donc que la méthode _@Parameters_ soit exécutée avant la phase d'initialisation de _ClassRule_, ce qui rend les scénarios comme ci-dessus un peu compliqués.

Commentaire le plus utile

Solution de contournement actuelle :

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Cela fonctionne mais il a besoin de ce nettoyage manuel...

Tous les 9 commentaires

Solution de contournement actuelle :

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Cela fonctionne mais il a besoin de ce nettoyage manuel...

+1

En y réfléchissant un peu, je suppose qu'un bon moyen d'implémenter cela serait d'introduire une annotation pour ceci:

<strong i="7">@Parameters</strong>
<strong i="8">@AfterClassRules</strong>
public Object[][] generateParameters() {
    // do stuff
}

Cela garantirait que les deux variantes sont toujours utilisables et que le code existant n'est pas cassé. Si cette conception est acceptable pour les responsables, je commencerais à travailler sur une demande d'extraction pour cela.

J'écris un commentaire supplémentaire car je ne sais pas si une mise à jour sur un commentaire déclenche une notification.

La conception proposée dans mon commentaire précédent serait-elle acceptable pour les mainteneurs ? Si c'est le cas, je commencerais à travailler sur une pull-request.

Il y a un problème architectural assez difficile ici : JUnit promet aux exécuteurs comme Eclipse qu'il peut énumérer le nombre de tests qu'il y a avant que l'un des tests ne soit exécuté, mais veut également minimiser les ressources consommées pendant cette phase de planification. Nous voulons donc vraiment savoir combien de paramètres il y aura avant de créer, par exemple, des dossiers temporaires ou de faire les choses encore plus drastiques qui apparaissent dans ClassRules, comme le démarrage des serveurs.

Ma réponse préférée serait peut-être d'activer quelque chose comme @DataPoints dans Theories : il peut y avoir des champs statiques ou des méthodes statiques préfixés par @ParameterSet , qui sont réunis pour créer le jeu de paramètres complet. Donc ton exemple serait :

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet public static Object[] first = new Object[] { 0 } ;
@ParameterSet objet statique public[] seconde() {
return new Object[] { tmp.getRoot().getPath(); }
}

Le point ici est que nous pourrions compter la méthode "seconde" sans l'exécuter réellement.

Qu'est-ce que tu penses?

Hm, je suppose que maintenant que j'y pense, le problème est en fait plus une odeur dans mon code de test. Je me connecte à un service distant et j'exécute des tests en fonction de sa configuration. Au lieu de cela, je devrais probablement simplement corriger la configuration attendue dans mon test.

Voici le test où j'ai initialement rencontré le problème : CryptoAppExecReturnCodeTest.java

@dsaff Je vais réfléchir à votre suggestion. L'impression initiale est la suivante : diviser des paires en tableaux séparés nécessite une attention particulière aux positions des éléments (un peu sujet aux erreurs). Je peux donc finir par remplir _first_ avec des trucs factices (juste en maintenant le nombre d'éléments); et en _seconde_ - je voudrais garder les éléments de la paire les uns à côté des autres :

{ 0, tmp...getPath() },
{ 1, ... }

Y a-t-il autre chose dont les coureurs ont besoin en plus du nombre de tests ? (Par exemple - peut-être tester les noms ?)

@javornikolov , je viens de réaliser que j'avais mal lu votre message initial, et donc ma réponse était probablement déroutante. Je lisais votre test comme deux instanciations différentes d'une classe de test construite avec un paramètre; maintenant que je l'ai relu, c'est en fait une instanciation d'une classe de test qui est construite avec deux paramètres. Pour ajuster ma proposition alors, le code suggéré serait:

<strong i="7">@ClassRule</strong> public static TemporaryFolder tmp = new TemporaryFolder();
<strong i="8">@ParameterSet</strong> public static Object[] only() {
return new Object[] { 0, tmp.getRoot().getPath(); }
}

J'espère que cela rend mon intention plus claire; désolé pour ma confusion initiale.

(en passant par quelques vieux bugs)

Peut-être devrions-nous renommer ce problème "Activer quelque chose comme @DataPoints dans les théories" ?

(en passant par quelques vieux bugs)

Peut-être devrions-nous renommer ce problème "Activer quelque chose comme @DataPoints dans les théories" ?

Je dirais que le problème est d'avoir la possibilité d'utiliser des ressources Rule dans la liste des paramètres pour les tests paramétrés. L'approche avec @ParameterSet proposée par @dsaff me semble viable (en supposant que les évaluations se produisent dans un ordre tel que le problème d'origine est résolu).
Mais si "Quelque chose comme @DataPoints" est suffisamment clair et qu'il n'y a aucun risque de diverger dans une direction ne couvrant pas le scénario d'origine : OK pour moi.
La raison pour laquelle je préfère les tests paramétrés aux théories (qui utilisent des points de données) est que les résultats de ces derniers ne sont pas rapportés indépendamment pour chaque ensemble de paramètres, et que le premier échec interrompt l'exécution des paramètres suivants.

Cette page vous a été utile?
0 / 5 - 0 notes