ファイルを利用したテストを行う際に、ファイルのクリーンアップを行うのは面倒な作業です。 インメモリでファイルシステムを模倣するJimfs を利用することも出来ますが、JUnit 5 では JUnit 4 では、以下のように JUnit 5 では、 JUnit 5 における一時ディレクトリサポートは、JUnit 5.4 で EXPERIMENTAL(実験的)機能として追加され、JUnit 5.10 にて STABLE(安定版) になりました。 JUnit 5 における一時ディレクトリサポートは、拡張機能として提供されていますが、デフォルトでこの拡張機能が組み込まれているため、 メソッドパラメータに 以下のように複数の一時ディレクトリを扱うこともできます。 テストクラスのインスタンスフィールドで一時ディレクトリを定義することもできます。この場合でも、複数のテストメソッドでは、それぞれ別の一時ディレクトリとなります( すべてのテストメソッドで同じ一時ディレクトリを使う場合は、 一時ディレクトリは、テスト完了時にクリーンアップされます。 この挙動は、 指定しない場合は、 一時ディレクトリの生成は デフォルトでは、以下のような つまり、Java の この挙動は、 指定するファクトリは、 この例では、一時ディレクトリのプレフィックスにテスト名を付与したものです。 一時ディレクトリはテスト終了時に自動的に削除されますが、何かの都合で削除できずに例外となることがあります。 通常はストリームのクローズ漏れに起因し、別プロセスで利用されているため削除できません のような形で例外となることがあります(特に Windows)。 ストリームのクローズを正しく処理するのが一番ですが、管理外のライブラリに起因する場合などは、以下のように JUnit 5.10 で安定版となった
はじめに
@TempDir により、この作業を軽減できます。JUnit 5 における一時ディレクトリサポート
@Rule で TemporaryFolder を使っていました。 public static class HasTempFolder {
@Rule
public TemporaryFolder folder= new TemporaryFolder();
@Test
public void testUsingTempFolder() throws IOException {
File createdFile= folder.newFile("myfile.txt");
// ...
}
}
@TempDir アノテーションにより以下のように一時ディレクトリを利用できます。@Test
void writeItemsToFile(@TempDir Path tempDir) throws IOException {
Path file = tempDir.resolve("test.txt");
// ...
}
@TempDir support for temporary directories@API(status = EXPERIMENTAL, since = "5.4")
@TempDir can be used to create multiple temporary directories
@TempDir
TempDirFactory SPI for customizing how temporary directories are created@API(status = STABLE, since = "5.10")@ExtendWith による登録作業は不要です。@TempDir の使い方
@TempDir を付けることで、一時ディレクトリを得ることができ、この一時ディレクトリは、テスト終了時に破棄されます。@Test void writeItemsToFile(@TempDir Path tempDir) throws Exception {
var file = tempDir.resolve("test.txt");
var lines = List.of("a", "b");
Files.write(file, lines);
assertLinesMatch(lines, Files.readAllLines(file));
}
@TempDir は、java.nio.file.Path または java.io.File に付与することができます。@Test void writeItemsToFile(@TempDir Path tempDir1,
@TempDir Path tempDir2) throws Exception {
}
@BeforeAll や @BeforeEach などのライフサイクルメソッドで初期設定を行い、テストメソッドで利用することができます)。class SharedTempDirectory {
@TempDir Path tempDir;
}
static フィールドに @TempDir でアノテートします。class SharedTempDirectory {
@TempDir static Path sharedTempDir;
@Test void test1() throws Exception { }
@Test void test2() throws Exception { }
}
一時ディレクトリのクリーンアップ
@TempDir アノテーションの cleanup 属性で変更できます(5.10 の段階では未だ EXPERIMENTAL)。@Test
void fileTest(@TempDir(cleanup = ON_SUCCESS) Path tempDir) {
// ...
}
cleanup 属性は以下があります。public enum CleanupMode {
DEFAULT, // junit.jupiter.tempdir.cleanup.mode.default の定義を利用
ALWAYS, // 常にクリーンアップ
ON_SUCCESS,// テスト成功時にクリーンアップ
NEVER; // クリーンアップなし
}
CleanupMode.DEFAULT となり、junit.jupiter.tempdir.cleanup.mode.default で定義されたクリーンアップモードを使うようになっています(この設定は、CleanupMode.ALWAYS が設定されています)。一時ディレクトリ生成のカスタマイズ
TempDirFactory を介して行われます。public interface TempDirFactory extends Closeable {
Path createTempDirectory(AnnotatedElementContext elementContext,
ExtensionContext extensionContext) throws Exception;
@Override
default void close() throws IOException {
}
TempDirFactory.Standard により一時ディレクトリが作成されます。class Standard implements TempDirFactory {
public static final TempDirFactory INSTANCE = new Standard();
private static final String TEMP_DIR_PREFIX = "junit";
@Override
public Path createTempDirectory(AnnotatedElementContext elementContext,
ExtensionContext extensionContext) throws IOException {
return Files.createTempDirectory(TEMP_DIR_PREFIX);
}
}
java.io.tmpdir プロパティのディレクトリ内に、junit というプレフィックス付きで一時ディレクトリが作成されます。@TempDir アノテーションの factory 属性にファクトリを指定することで変更できます(5.10 の段階では未だ EXPERIMENTAL)(設定 junit.jupiter.tempdir.factory.default により設定することも可能)。@Test void fileTest(@TempDir(factory = MyFactory.class) Path tempDir) {
// ...
}
TempDirFactory を実装して以下のように実装できます。static class MyFactory implements TempDirFactory {
@Override
public Path createTempDirectory(AnnotatedElementContext elementContext,
ExtensionContext extensionContext) throws IOException {
return Files.createTempDirectory(
extensionContext.getRequiredTestMethod().getName());
}
}
まとめ
System.gc() を強制することで対応することができます。@AfterEach
@EnabledOnOs(OS.WINDOWS)
void cleanUp() {
System.gc();
}
まとめ
@TempDir による一時ディレクトリサポートについて説明しました。
@TempDir を付けることで、一時ディレクトリを得る@TempDir の cleanup 属性で、一時ディレクトリのクリーンアップの振る舞いをカスタマイズ@TempDir の factory 属性で、一時ディレクトリの生成をカスタマイズ
