Как правильно записать временный файл во время модульных тестов с Maven?
Я написал модульный тест, который записывает файл в файловую систему, без указания пути, по которому он пишет в рабочий каталог; поэтому, если выполняется из каталога проекта, он записывает в корневой каталог проекта, если в родительском каталоге проектов он записывает в корневой каталог родителей.
Так каков правильный способ записи в целевой каталог? Вполне возможно, каталог внутри целевого каталога?
Если я просто укажу target/
с файлом он будет записывать в родительские цели проектов вместо целей проектов.
ОБНОВЛЕНИЕ: я на самом деле хочу файл после завершения теста. Файл предназначен для формата извлечения для третьих сторон, который необходимо отправить третьим лицам. Тест можно включить / выключить, чтобы разрешить запуск только в том случае, если формат файла изменяется для повторного утверждения. Это не большая проблема, где файл идет, но я хотел бы что-то, что легко найти.
8 ответов
Вы можете попробовать использовать TemporaryFolder JUnit @Rule, как описано здесь
TemporaryFolder создает папку в каталоге временных файлов по умолчанию, указанном системным свойством java.io.tmpdir. Метод newFile создает новый файл во временном каталоге, а newFolder создает новую папку.
Когда тестовый метод заканчивается, JUnit автоматически удаляет все файлы и каталоги, включая TemporaryFolder. JUnit гарантирует удаление ресурсов, независимо от того, пройден тест или нет.
После обновления вопроса
Вы можете изменить рабочий каталог, используемый maven-surefire-plugin
,
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.3</version>
<configuration>
<workingDirectory>${project.build.directory}</workingDirectory>
</configuration>
</plugin>
[...]
</plugins>
Вы можете изменить этот рабочий каталог на что угодно для ваших тестов, например ${project.build.directory}/my_special_dir/
,
Рабочий каталог в плагине surefire влияет только на выполняемые тесты и ТОЛЬКО на тесты, проводимые maven. Если вы запускаете свои тесты из среды IDE, рабочий каталог будет чем-то другим.
Не нужно изобретать велосипед...
JDK предоставляет способ создания временного файла и способ его автоматического удаления при выходе:
File file = File.createTempFile( "some-prefix", "some-ext");
file.deleteOnExit();
Используйте файл, и он будет автоматически удален после завершения теста. Это все, что нужно сделать.
Чтобы указать каталог для временных файлов, используйте перегруженный метод:
File file = File.createTempFile( "prefix", "ext", new File("/some/dir/path"));
Начиная с JUnit 5 вы можете использовать @TempDir . Он будет удален (включая его содержимое) после тестирования.
либо один временный каталог для каждого теста:
@Test
void testWithTempFiles(@TempDir Path tempDir)
Path file = dir.resolve("temp_file.txt");
...
}
или один для всех тестов в классе:
@TempDir
static Path tempDir
@Test
void testWithTempFiles()
Path file = dir.resolve("temp_file.txt");
...
}
Чтобы заявить об этом заранее, я категорически против делать такие вещи в модульном тестировании. Я действительно не пробовал это, но это должно работать:
Предположим, вы используете плагин surefire, из документа, который он цитировал, вы можете получить доступ к базовому каталогу тестируемого проекта с помощью System.getProperty("basedir")
, Получите его и создайте файлы в basedir / target.
Более "подходящий" способ (поскольку у нас может быть шанс, что мы настроили выходной каталог на что-то другое, вы можете изменить конфигурацию плагина surefire на что-то вроде этого:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<systemPropertyVariables>
<myOutDir>${project.build.outputDirectory}</myOutDir>
</systemPropertyVariables>
</configuration>
</plugin>
Тогда вы можете получить фактический выходной каталог по System.getProperty("myOutDir")
в вашем тесте.
Я написал бы подпрограмму, которая определяет, куда файл должен быть записан, и который я потом использую, в общем, я стараюсь избегать (насколько это возможно) доступа к постоянным данным в юнит-тестах, таких как файловый ввод-вывод или доступ к базе данных, это имеет соображения производительности и другие тоже,
Посмотрите на этот ответ: /questions/46370608/modulnoe-testirovanie-fajlov-vvoda-vyivoda/46370702#46370702
Вы захотите иметь возможность запускать свои тесты как из IDE, так и из Maven, поэтому лучше всего писать свои тесты, чтобы они не предполагали, что они выполняются в Maven.
Одним из лучших способов работы с временными файлами является использование правил junit. Это позволяет вам полагаться на правило для очистки для вас.
Временные файлы должны быть созданы во временный каталог. Получить его с помощью вызова System.getProperty("java.io.tmpdir")
Временный файл должен быть временным, т.е. должен быть удален, когда он не нужен. Чтобы добиться этого, не забудьте удалить его в finally
блок или код, который запускается после теста, то есть:
File tmpFile = ...
try {
// deal with tempFile
} finally {
tempFile.delete();
}
и / или
public class MyTestCase {
private File tmpFile = null;
@Before
public void setUp() {
tmpFile = ...;
}
@Test
public void setUp() {
// deal with tmpFile
}
@After
public void setUp() {
tmpFile.delete();
}
}
использование File.createTempFile(String prefix, String suffix)
если это возможно, то есть вы можете использовать файл со специальным именем, созданным createTempFile()
,
использование file.deleteOnExit()
, Это создает ловушку, которая автоматически удаляет файл, когда JVM завершается. Файл останется, только если JVM была убита kill -9
, так что у него не было возможности запустить код завершения работы.
Вот несколько способов использования JUnit 5 и языка Kotlin.
Использование JUnit 5 в поле:
@TempDir(cleanup = ON_SUCCESS) lateinit var tempDirectory: Path @Test fun example() { // use the tempDirectory }
Использование JUnit 5
@TempDir
по параметру тестовой функции:@Test fun example( @TempDir(cleanup = CleanupMode.ON_SUCCESS) tempDirectory: Path ) { // use the tempDirectory }
Создание файла вручную и вызов
deleteOnExit()
:@Test fun example() { val file = File("file.txt").apply { deleteOnExit() } }
Использование Котлина
createTempDirectory
иcreateTempFile
функции в тестовом классе или тестовой функции:val file = createTempFile("file.txt")