JavaFx MediaPlayer ведет себя по-разному в модульном тесте и приложении, почему?

Я хочу загрузить метаданные из файла MP3 для воспроизведения с помощью JavaFx MediaPlayer. Это отлично работает в модульном тесте, но не в приложении. В модульном тесте было сообщено 6 элементов метаданных, но ноль в приложении. Метод, который «делает работу», тот же.

Основной класс приложения расширяет Application. Тестовый класс расширяет ApplicationTest от TestFx. Могло ли это повлиять на поведение?

Приложение:

public class MediaMain extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        Map<String, Object> meta = metaData();

        System.out.printf("Number of meta data: %d.%n", meta.size());
        System.out.println(meta);
    }

    Map<String, Object> metaData() {
        File audioFile = new File("src/main/resources", "beingBoiled.mp3");
        final URI uri = audioFile.toURI();
        final String source = uri.toString();
        Media media = new Media(source);
        new MediaPlayer(media);
        return media.getMetadata();
    }
}

Модульный тест:

class MediaMainTest extends ApplicationTest {

    @Test
    void testMeta() {
        MediaMain main = new MediaMain();

        Map<String, Object> metaData = main.metaData();

        assertNotEquals(0, metaData.size());
        System.out.printf("Number of meta data: %d.%n", metaData.size());
        System.out.println(metaData);
    }
}

Распечатка из приложения:

Number of meta data: 0.
{}

Распечатка модульного теста:

Number of meta data: 6.
{year=1980, artist=The Human League, raw metadata={ID3=java.nio.HeapByteBufferR[pos=254 lim=3214 cap=3214]}, album=Travelogue, genre=(52), title=Being Boiled}

Что может быть причиной? Это загадка для меня. Написано с использованием Java 11, JavaFx 11.0.2 и TestFx 4.0.15-alpha.


person Helge    schedule 10.10.2019    source источник
comment
Метаданные Media загружаются лениво, что означает, что они могут быть доступны не сразу. Вы можете просматривать метаданные, чтобы получать уведомления, когда становятся известны определенные атрибуты.   -  person Slaw    schedule 10.10.2019


Ответы (1)


Вы ссылаетесь на файл с местоположением src/main/resources, это, вероятно, не очень хорошая идея, поскольку ваше развернутое приложение, скорее всего, не будет иметь каталог src/main/resources, плюс ресурс может быть упакован в банку приложения, а не как файл на диске, поэтому использование файлового протокола для доступа к нему не сработает.

Вероятно, лучше всего использовать что-то вроде следующего:

String mediaLoc = getClass().getResource("/beingBoiled.mp3").toExternalForm()
Media media = new Media(mediaLoc)

Как в Как загрузить файл css в javafx8. Точное расположение загружаемого ресурса может отличаться в зависимости от сборки и структуры проекта. Если вы не хотите загружать из пути к классу, а вместо этого через файл или сетевой http-вызов, вам нужно будет использовать что-то еще.

Приведенный выше код предполагает, что ваша система сборки настроена на копирование носителя из src/main/resources в целевое расположение упаковки и упаковку ресурса в распространяемый файл приложения (например, файл jar приложения) в корне файла jar.

Убедитесь, что ваша система сборки действительно копирует файл в целевое расположение. Вы можете проверить, есть ли он там, запустив свою сборку, посмотрев полученный jar и запустив jar tvf <myjarfilename>.jar, чтобы увидеть, находится ли ресурс mp3 в правильном месте в корне файла jar.

person jewelsea    schedule 10.10.2019
comment
В конце концов, я не буду загружать аудиофайлы из папки ресурсов, это временное решение. Если я запущу плеер проверенным методом, песня будет играть и в приложении, и в юнит-тесте. но метаданные все равно будут отсутствовать в приложении. Я работаю в IDE IntelliJ, последней версии сообщества, на Mac и Windows. - person Helge; 10.10.2019
comment
Метаданные представляют собой ObservableMap, их содержимое может меняться со временем в зависимости от загруженного мультимедиа и состояния медиаплеера. Попробуйте прослушивать изменения на карте и регистрировать их. - person jewelsea; 10.10.2019
comment
Когда я запускаю проверенный метод в двух контекстах (класс Main и класс MediaMainTest, расширяющий класс ApplicationTest), я тестировал с задержками до запроса метаданных (ничего не менял), а также смотрел на состояние проигрывателя. Это другое; в приложении MediaMain он сообщается как UNKNOWN даже после запуска проигрывателя, тогда как для модульного теста он меняется на READY или PLAYING, по крайней мере, после подходящей задержки. - person Helge; 11.10.2019
comment
Я убежден, что разница заключается в том, как отличается контекст между классом MediaMain, расширяющим Application, и модульным тестом в классе MediaMainTest, расширяющим ApplicationTest. Но я не понимаю, как. - person Helge; 11.10.2019
comment
Если вы еще этого не сделали, попробуйте то, что я предложил, добавить прослушиватель к ObservableMap метаданных и зарегистрировать его изменения. Кроме того, исходный код в мультимедийном пакете Javadoc включает исчерпывающую информацию о ведении журналов и отчетах об исключениях для использования носителя. Пожалуйста, реализуйте все это и изучите логи. - person jewelsea; 11.10.2019
comment
Пример отображения метаданных и использования для них прослушивателя изменений см. в разделе: Воспроизведение списка аудиофайлов в JavaFX. , отображая метаданные мультимедиа каждого файла, который отвечает Java Music Player : Информация о песне и воспроизведение. - person jewelsea; 11.10.2019
comment
Использование слушателя решает мою реальную проблему с приложением, хотя и не проблему, описанную здесь (почему один и тот же метод ведет себя по-разному в двух случаях использования). Что интересно для класса MediaMain, так это то, что когда я добавлял прослушиватель, он вызывался только после выхода из метода запуска. В моем реальном приложении я хочу обновить текстовое поле либо в графическом интерфейсе Swing, либо в графическом интерфейсе JavaFx. Теперь это работает, так что я доволен. - person Helge; 11.10.2019