Junit4: @Parameters-Methode wird vor der @ClassRule-Initialisierung ausgeführt. Kann es sein, dass es umgekehrt ist?

Erstellt am 2. Mai 2013  ·  9Kommentare  ·  Quelle: junit-team/junit4

Ich habe folgendes Problem (mit _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()}
        });
    }

Dies führt zu initializationError

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

Also scheint die _@Parameters_ -Methode vor der _ClassRule_-Initialisierungsphase ausgeführt zu werden, was Szenarien wie das obige etwas komplizierter macht.

Hilfreichster Kommentar

Aktuelle Problemumgehung:

    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();
    }

Es funktioniert, aber es braucht diese manuelle Bereinigung ...

Alle 9 Kommentare

Aktuelle Problemumgehung:

    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();
    }

Es funktioniert, aber es braucht diese manuelle Bereinigung ...

+1

Wenn ich ein wenig darüber nachdenke, denke ich, dass eine gute Möglichkeit, dies zu implementieren, darin besteht, eine Anmerkung dafür einzuführen:

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

Damit wäre sichergestellt, dass beide Varianten weiterhin nutzbar sind und bestehender Code nicht kaputt geht. Wenn dieses Design für die Betreuer akzeptabel ist, würde ich mit der Arbeit an einem Pull-Request dafür beginnen.

Ich schreibe einen zusätzlichen Kommentar, weil ich nicht sicher bin, ob eine Aktualisierung eines Kommentars eine Benachrichtigung auslöst.

Wäre das in meinem vorherigen Kommentar vorgeschlagene Design für die Betreuer akzeptabel? Wenn ja, würde ich mit der Arbeit an einem Pull-Request beginnen.

Hier gibt es ein ziemlich schwieriges Architekturproblem: JUnit verspricht Runnern wie Eclipse, dass es aufzählen kann, wie viele Tests es gibt, bevor einer der Tests ausgeführt wird, möchte aber auch alle während dieser Planungsphase verbrauchten Ressourcen minimieren. Wir wollen also wirklich wissen, wie viele Parameter es geben wird, bevor wir zum Beispiel temporäre Ordner erstellen oder die noch drastischeren Dinge tun, die in ClassRules auftauchen, wie das Starten von Servern.

Vielleicht wäre meine Lieblingsantwort, so etwas wie @DataPoints in Theories zu aktivieren: Es kann statische Felder oder statische Methoden mit dem Präfix @ParameterSet geben , die zusammengefügt werden, um den vollständigen Parametersatz zu erstellen. Dein Beispiel wäre also:

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet öffentliches statisches Objekt[] zuerst = neues Objekt[] { 0 };
@ParameterSet öffentliches statisches Objekt[] second() {
return new Object[] { tmp.getRoot().getPath(); }
}

Der Punkt hier ist, dass wir die Methode "zweite" zählen könnten, ohne sie tatsächlich auszuführen.

Was denken Sie?

Hm, ich denke jetzt, wo ich darüber nachdenke, ist das Problem eigentlich eher ein Geruch in meinem Testcode. Ich verbinde mich mit einem Remote-Dienst und führe Tests durch, je nachdem, wie er konfiguriert ist. Stattdessen sollte ich wahrscheinlich einfach die erwartete Konfiguration in meinem Test korrigieren.

Hier ist der Test, bei dem ich ursprünglich auf das Problem gestoßen bin: CryptoAppExecReturnCodeTest.java

@dsaff Ich werde über deinen Vorschlag nachdenken. Der erste Eindruck ist: Das Aufteilen von Paaren in separate Arrays erfordert eine besondere Sorgfalt bei den Positionen der Elemente (etwas fehleranfällig). So kann es sein, dass ich _zuerst_ mit etwas Dummy-Zeug auffülle (nur um die Anzahl der Elemente beizubehalten); und in _second_ - ich möchte die Paarelemente nebeneinander halten:

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

Gibt es neben der Anzahl der Tests noch etwas, was Läufer brauchen? (zB - vielleicht Testnamen?)

@javornikolov , mir ist gerade aufgefallen, dass ich Ihren ersten Beitrag falsch gelesen habe, und daher war meine Antwort wahrscheinlich verwirrend. Ich habe Ihren Test als zwei verschiedene Instanziierungen einer Testklasse gelesen, die mit einem Parameter erstellt wurde. Jetzt, wo ich es noch einmal lese, ist es tatsächlich eine Instanziierung einer Testklasse, die mit zwei Parametern erstellt wird. Um meinen Vorschlag dann anzupassen, wäre der vorgeschlagene Code:

<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(); }
}

Ich hoffe, das macht meine Absicht klarer; sorry für meine anfängliche Verwirrung.

(einige alte Bugs durchgehen)

Vielleicht sollten wir dieses Problem umbenennen in "So etwas wie @DataPoints in Theorien aktivieren"?

(einige alte Bugs durchgehen)

Vielleicht sollten wir dieses Problem umbenennen in "So etwas wie @DataPoints in Theorien aktivieren"?

Ich würde sagen, das Problem besteht darin, die Möglichkeit zu haben, Rule -Ressourcen in der Liste der Parameter für parametrisierte Tests zu verwenden. Der von @dsaff vorgeschlagene Ansatz mit @ParameterSet scheint mir praktikabel (vorausgesetzt, die Bewertungen erfolgen in einer solchen Reihenfolge, dass das ursprüngliche Problem behoben ist).
Aber wenn "Something like @DataPoints" klar genug ist und kein Risiko besteht, in eine Richtung abzuweichen, die das ursprüngliche Szenario nicht abdeckt: OK für mich.
Der Grund, warum ich parametrisierte Tests gegenüber Theorien (die Datenpunkte verwenden) bevorzuge, ist, dass die Ergebnisse der letzteren nicht unabhängig für jeden Satz von Parametern gemeldet werden und dass der erste Fehler die Ausführung der nachfolgenden Parameter abbricht.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen