37

Junit テスト ケース内で実行される組み込みサーバーを使用しています。これらのサーバーには、作業ディレクトリが必要な場合があります (Apache ディレクトリ サーバーなど)。

Junit 4.7 の新しい @Rule は、これらのケースを処理できます。TemporaryFolder-Rule は、一時ディレクトリを作成できます。サーバー用にカスタムの ExternalResource-Rule を作成できます。しかし、あるルールの結果を別のルールに渡したい場合は、どうすればよいですか。

import static org.junit.Assert.assertEquals;
import java.io.*;
import org.junit.*;
import org.junit.rules.*;

public class FolderRuleOrderingTest {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Rule
    public MyNumberServer server = new MyNumberServer(folder);

    @Test
    public void testMyNumberServer() throws IOException {
        server.storeNumber(10);
        assertEquals(10, server.getNumber());
    }

    /** Simple server that can store one number */
    private static class MyNumberServer extends ExternalResource {

        private TemporaryFolder folder;

        /** The actual datafile where the number are stored */
        private File dataFile;

        public MyNumberServer(TemporaryFolder folder) {
            this.folder = folder;
        }

        @Override
        protected void before() throws Throwable {
            if (folder.getRoot() == null) {
                throw new RuntimeException("TemporaryFolder not properly initialized");
            }

            //All server data are stored to a working folder
            File workingFolder = folder.newFolder("my-work-folder");
            dataFile = new File(workingFolder, "datafile");
        }

        public void storeNumber(int number) throws IOException {
            dataFile.createNewFile();
            DataOutputStream out = new DataOutputStream(new FileOutputStream(dataFile));
            out.writeInt(number);
        }

        public int getNumber() throws IOException {
            DataInputStream in = new DataInputStream(new FileInputStream(dataFile));
            return in.readInt();
        }
    }
}

このコードでは、サーバーがデータを格納する作業ディレクトリを作成できるように、フォルダーがパラメーターとしてサーバーに送信されます。ただし、Junit はファイルで定義されているルールとは逆の順序でルールを処理するため、これは機能しません。TemporaryFolder ルールは、サーバー ルールの前には実行されません。したがって、TempraryFolder のルート フォルダーは null になり、その結果、現在の作業ディレクトリを基準にしてファイルが作成されます。

クラスの属性の順序を逆にすると、変数を定義する前に参照できないため、コンパイル エラーが発生します。

Junit 4.8.1 を使用しています (ルールの順序が 4.7 リリースから少し修正されたため)

4

4 に答える 4

49

編集:最近リリースされたJunit 4.10を使用するRuleChainと、ルールを正しく連鎖させるために使用できます(最後を参照)。

@Ruleアノテーションなしで別のプライベートフィールドを導入してから、必要に応じてコードを並べ替えることができます。

public class FolderRuleOrderingTest {

    private TemporaryFolder privateFolder = new TemporaryFolder();

    @Rule
    public MyNumberServer server = new MyNumberServer(privateFolder);

    @Rule
    public TemporaryFolder folder = privateFolder;

    @Test
    public void testMyNumberServer() throws IOException {
        server.storeNumber(10);
        assertEquals(10, server.getNumber());
    }
    ...
}

最もクリーンな解決策は複合ルールを使用することですが、上記は機能するはずです。

RuleChain編集:最近リリースされたJunit 4.10では、ルールを正しく連鎖させるために使用できます。

public static class UseRuleChain {
   @Rule
   public TestRule chain = RuleChain
                          .outerRule(new LoggingRule("outer rule"))
                          .around(new LoggingRule("middle rule"))
                          .around(new LoggingRule("inner rule"));

   @Test
   public void example() {
           assertTrue(true);
   }
}

ログを書き込みます

starting outer rule
starting middle rule
starting inner rule
finished inner rule
finished middle rule
finished outer rule
于 2011-09-22T13:55:56.943 に答える
3

通常の解決策が見つからない場合は、@Rule他のすべてを含む複合ルール (および注釈を持つ唯一のルール) をいつでも作成して、それらを順番に実行できます。

于 2010-04-29T09:07:47.637 に答える
0

MyNumberServerまたは、コンストラクターでフォルダーを指定する代わりに、ルールでセッターを提供することもできます。

さらに、ルール間の順序付けは、説明した方法で保証されるわけではありません。特にルール間の通信が必要な場合は、少しトリッキーになる可能性があります。たとえば、テストが失敗したときに例外をログに記録する最良の方法 (たとえば、junit ルールを使用) を参照してください。

于 2011-09-22T13:42:01.740 に答える