Я пишу инструмент командной строки, который генерирует текстовые файлы. Я хочу написать тест JUnit 5, который сравнивает сгенерированный файл с ресурсом теста.
Чтобы тесты не «загрязняли» файловую систему, я использую пакет Google Jimfs, т.е. перед каждым тестом я настраиваю файловую систему с помощью
fileSystem = Jimfs.newFileSystem(Configuration.unix());
Средство командной строки написано так, что он использует эту файловую систему во время теста и «нормальную» файловую систему во время нормального выполнения. Это отлично работает.
Когда я запускаю JUnit 5 в IDE (Eclipse 2019-03), кажется, что файл тестового ресурса находится как «обычный файл», так что в моем тестовом коде я могу использовать Java 8 NIO пакет для чтения файла, .eg:
Path p = = fileSystem.getPath("...");
// Now read the file in using the Path p
Это отлично работает. Однако, когда я использую Gradle для создания исполняемого JAR-файла, файл ресурса теперь рассматривается как правильный ресурс, и код должен прочитать его, используя что-то вроде:
URI uri = ClassLoader.getSystemResource(resourceFileName).toURI();
// Now read the file in using the URI.
Это означает, что у меня либо есть два набора тестового кода, один для запуска в Eclipse и один для запуска в Gradle (не совсем правильное решение) или - как я уже сделал - написал следующую утилиту:
private Path getResourcePath(String resourceFileName) throws URISyntaxException, IOException {
Path resourcePath;
URI uri = ClassLoader.getSystemResource(resourceFileName).toURI();
// Now check if the system resource is either a normal file (e.g. we are running in an IDE) or
// the system resource is is a packaged JAR (e.g. we are running a packaged JAR file)
if (uri.getScheme().equalsIgnoreCase("jar")) {
// Running as a packaged JAR so set up a file system to read this jar using the first
// part of the URI (separated with '!') as the file to use
String[] uriParts = uri.toString().split("!");
try {
jarFileSystem = FileSystems.getFileSystem(URI.create(uriParts[0]));
}
catch(FileSystemNotFoundException e) {
jarFileSystem = FileSystems.newFileSystem(URI.create(uriParts[0]), new HashMap<>());
}
resourcePath = jarFileSystem.getPath(uriParts[1]);
} else {
// Assume that the system resource is a normal file (e.g. we are running in an IDE).
String pathName = uri.getSchemeSpecificPart();
// If there is a leading '/' then remove it if we run on Windows so we have a correct path specification.
// TODO is there some way to remove this "special" case.
if (runsOnWindows() && pathName.startsWith("/")) {
pathName = pathName.substring(1);
}
// The resource file is in the default file system and not any file system
// that is being used for e.g. test. Returned path should therefore be
// associated with the default file system.
FileSystem fs = FileSystems.getDefault();
resourcePath = fs.getPath(pathName);
}
return resourcePath;
}
Кажется, это работает. Однако, это все еще не кажется мне лучшим решением. Есть ли способ избавить меня от необходимости писать этот неуклюжий код? Может быть, что-то в Eclipse или JUnit 5 или Gradle или ... что-то еще? Или я что-то упустил абсолютно базовый c?