ClassLoader не находит файлы ресурсов после сборки - PullRequest
0 голосов
/ 27 сентября 2018

Я столкнулся с проблемами при попытке заставить Java ClassLoader извлекать файлы JSON из каталога test/resources после развертывания.

public class TestFileUtil {
    private static final ClassLoader classLoader = TestFileUtil.class.getClassLoader();

    public static Map<String, Object> getJsonFileAsMap(String fileLocation) {

        try {
            return new ObjectMapper().readValue(getTestFile(fileLocation), HashMap.class);
        } catch (IOException e) {
            throw new RuntimeException("Error converting JSON file to a Map", e);
        }
    }

    private static File getTestFile(String fileLocation) {

        return new File(classLoader.getResource(fileLocation).getFile());
    }
}

У утилиты нет проблем во время локального тестирования с Mockito, например:

public class LocalTest {

    @Before
    public void setUp() {
        Mockito.when(mockDataRetrievalService.getAssetJsonById(Mockito.any())).thenReturn(TestFileUtil.getJsonFileAsMap("test.json"));
    }
}

Однако эта строка вызывает исключение FileNotFound при сборке в наших развернутых средах.

При использовании относительного пути к каталогу "../../test.json" в обеих средах наблюдаются исключения FileNotFound.

Структура локального каталога:

test
| java
| |- project
| |  |- LocalTest
| |- util
| |  |- TestFileUtil.class
| resources
| |- test.json

После развертывания:

test
| com
| | project
| | | dao
| | | | LocalTest
| | other project
| | | | util
| | | | | TestFileUtil.class
| | | | | test.json

Существует ли какое-либо специальное поведение или необходимая структура каталога, связанная с использованием ClassLoader в автоматических сборках?

1 Ответ

0 голосов
/ 28 сентября 2018

Скорее всего, проблема заключается в следующем:

new File(classLoader.getResource(fileLocation).getFile());

Метод getFile () класса URL не возвращает верное имя файла.Он просто возвращает часть пути URL, которая не обязательно является допустимым именем файла.(Имя метода имело смысл, когда класс URL был введен как часть Java 1.0, поскольку практически все URL действительно ссылались на физические файлы, либо на том же компьютере, либо на другом компьютере.)

Аргументв ClassLoader.getResource не является именем файла.Это относительный URL, основой которого является каждое местоположение в пути к классам ClassLoader.Если вы хотите прочитать ресурс, связанный с вашим приложением, не пытайтесь преобразовать URL ресурса в файл.Вместо этого прочитайте URL как URL:

public class TestFileUtil {
    private static final ClassLoader classLoader = TestFileUtil.class.getClassLoader();

    public static Map<String, Object> getJsonFileAsMap(String fileLocation) {

        try {
            return new ObjectMapper().readValue(getTestFile(fileLocation), HashMap.class);
        } catch (IOException e) {
            throw new RuntimeException("Error converting JSON file to a Map", e);
        }
    }

    private static URL getTestFile(String fileLocation) {

        return classLoader.getResource(fileLocation);
    }
}

Если вы хотите прочитать файл, который не является частью вашего приложения, вообще не используйте getResource.Просто создайте экземпляр File.

...