Junit4: @Parametersメソッドは、@ ClassRuleの初期化の前に実行されます。 それは回避策でしょうか?

作成日 2013年05月02日  ·  9コメント  ·  ソース: junit-team/junit4

私は次の問題を抱えています(_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()}
        });
    }

これにより、 initializationErrorが発生します

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

したがって、 _ @ Parameters_メソッドは_ClassRule_初期化フェーズの前に実行されるため、上記のようなシナリオは少し複雑になります。

最も参考になるコメント

現在の回避策:

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

動作しますが、手動でクリーンアップする必要があります...

全てのコメント9件

現在の回避策:

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

動作しますが、手動でクリーンアップする必要があります...

+1

少し考えてみると、これを実装する良い方法は、これに注釈を付けることだと思います。

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

これにより、両方のバリアントが引き続き使用可能であり、既存のコードが壊れていないことが保証されます。 この設計がメンテナに受け入れられる場合、私はこれのプルリクエストに取り組み始めます。

コメントの更新が通知をトリガーするかどうかわからないため、追加のコメントを書いています。

以前のコメントで提案された設計は、メンテナに受け入れられますか? もしそうなら、私はプルリクエストの作業を開始します。

ここにはかなり難しいアーキテクチャ上の問題があります。JUnitは、Eclipseのようなランナーに、テストを実行する前にテストの数を列挙できることを約束しますが、この計画フェーズで消費されるリソースを最小限に抑えたいと考えています。 したがって、たとえば、一時フォルダーを作成したり、サーバーの起動など、ClassRulesに表示されるさらに大幅な処理を実行したりする前に、パラメーターがいくつあるかを知りたいのです。

おそらく私のお気に入りの答えは、理論で@DataPointsのようなものを有効にすることです。静的フィールドまたは@ParameterSetのプレフィックスが付いた静的メソッドがあり、これらを結合して完全なパラメーターセットを作成できます。 したがって、あなたの例は次のようになります。

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet public static Object [] first = new Object [] {0};
@ParameterSet public static Object [] second(){
新しいオブジェクトを返す[] {tmp.getRoot()。getPath(); }
}

ここでのポイントは、実際に実行せずにメソッド「second」をカウントできることです。

どう思いますか?

うーん、今考えてみると、問題は実際には私のテストコードの匂いです。 リモートサービスに接続し、構成方法に応じてテストを実行しています。 代わりに、おそらくテストで予想される構成を修正する必要があります。

これが私が最初に問題に直面したテストです: CryptoAppExecReturnCodeTest.java

@dsaff私はあなたの提案についていくつか考えます。 最初の印象は次のとおりです。ペアを別々の配列に分割するには、要素の位置に特別な注意を払う必要があります(少しエラーが発生しやすい)。 だから私は_first_をいくつかのダミーのもので埋めてしまうかもしれません(要素の数を維持するだけです)。 そして_second_で-ペア要素を隣り合わせに保ちたい:

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

テストの数以外に、ランナーが必要とするものはありますか? (例-おそらくテスト名?)

@javornikolov 、私はあなたの最初の投稿を読み間違えたことに気づいたので、私の応答はおそらく混乱していました。 私はあなたのテストを、1つのパラメーターで構築されたテストクラスの2つの異なるインスタンス化として読んでいました。 もう一度読んだので、実際には2つのパラメーターで構築されたテストクラスの1つのインスタンス化です。 私の提案を調整するために、提案されたコードは次のようになります。

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

それが私の意図をより明確にすることを願っています。 最初の混乱でごめんなさい。

(いくつかの古いバグを通過します)

おそらく、この問題の名前を「理論で@DataPointsのようなものを有効にする」に変更する必要がありますか?

(いくつかの古いバグを通過します)

おそらく、この問題の名前を「理論で@DataPointsのようなものを有効にする」に変更する必要がありますか?

問題は、パラメーター化されたテストのパラメーターのリストでRuleリソースを使用できるようにすることです。 @dsaffによって提案された@ParameterSetを使用したアプローチは、私には実行可能であるように思われます(元の問題が解決されるような順序で評価が行われると仮定します)。
しかし、「@ DataPointsのようなもの」が十分に明確であり、元のシナリオをカバーしていない方向に分岐するリスクがない場合:私にとってはOKです。
理論(DataPointsを使用)よりもパラメーター化されたテストを好む理由は、後者の結果がパラメーターのセットごとに個別に報告されず、最初の失敗が後続のパラメーターの実行を中止するためです。

このページは役に立ちましたか?
0 / 5 - 0 評価