Использование Maven для создания отдельных файлов JAR для модульного тестирования загрузчика пользовательских классов - PullRequest
3 голосов
/ 10 сентября 2009

В рамках моего текущего проекта я создал собственный загрузчик классов. Часть модульных тестов для пользовательского загрузчика включает использование некоторых JAR-файлов для демонстрации правильного поведения загрузчика.

Я бы хотел собрать тестовые JAR-файлы из исходных текстов Java перед запуском реальных модульных тестов. Кроме того, тестовые JAR-файлы не могут находиться в пути к классам при выполнении модульных тестов, поскольку я хочу динамически загружать их во время выполнения теста.

Существует ли стандартная схема для выполнения такого типа требования "собрать несколько JAR-файлов на стороне до фазы тестирования, но не включать их в путь к классам"? Я не могу поверить, что я первый, кто попытался сделать это с Maven 2, но я не могу найти правильную структуру POM и зависимости. Обычно я заканчиваю тем, что некоторые jar-тесты не создаются перед фазой тестирования, но у меня также были проблемы с несогласованным порядком сборки, из-за которого сборка работала на одном компьютере должным образом, но некоторые сборки не выполнялись. тест баночки по другому.

Ответы [ 3 ]

5 голосов
/ 10 сентября 2009

Самое простое, что нужно сделать, это настроить другой проект для упаковки классов для тестового фляги, а затем установить его как нормальную тестовую область зависимость.

Если вы не хотите / не можете этого сделать, вы можете использовать плагин сборки, чтобы создать jar в фазе process-test-classes (т.е. после того, как тесты были скомпилированы, но до того, как тесты будут выполнены). Приведенная ниже конфигурация вызовет подключаемый модуль сборки, чтобы создать jar с именем classloader-test-deps на этом этапе в целевом каталоге. Ваши тесты могут затем использовать эту банку по мере необходимости.

Плагин сборки использует дескриптор сборки (в src / main / assembly, называемый test-assembly.xml), который упаковывает содержимое target / test-classes. Я установил фильтр для включения содержимого пакета com.test и его дочерних элементов. Это предполагает, что у вас есть соглашение об именах пакетов, которое вы можете применять для содержимого jar.

Плагин сборки по умолчанию прикрепит jar как дополнительный артефакт, указав attach как false, он не будет установлен / развернут.

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.2-beta-2</version>
  <executions>
    <execution>
      <id>create-test-dependency</id>
      <phase>process-test-classes</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <finalName>classloader-test-deps</finalName>
        <attach>false</attach>
        <descriptors>
          <descriptor>src/main/assembly/test-assembly.xml</descriptor>
        </descriptors>
      </configuration>
    </execution>
  </executions>
</plugin>

Это содержимое test-assembly.xml

<assembly>
  <id>test-classloader</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <fileSets>
    <fileSet>
      <directory>${project.build.testOutputDirectory}</directory>
      <outputDirectory>/</outputDirectory>
      <!--modify/add include to match your package(s) -->
      <includes>
        <include>com/test/**</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>
5 голосов
/ 10 сентября 2009

Я бы попытался настроить все необходимое для ваших тестов изнутри теста. Основным преимуществом является то, что не существует волшебной невидимой настройки, которая неявно присутствует в тесте. Тест может выполняться в любой среде. Кроме того, гораздо проще добавлять новые строго изолированные сценарии, поскольку вы не зависите от некоторых смешанных сценариев.

Настройка не должна быть слишком сложной:

  • сериализует Java-класс:
    • с некоторой библиотекой кодов типов
    • В качестве альтернативы используйте файл класса java, переименованный в некоторый суффикс файла, отличный от .class. Поместите его в папку ресурсов теста и загрузите с помощью загрузчика классов (getResourceAsStream (...)).
  • zip файл класса (`java.util.zip.GZIPOutputStream`)
  • загрузить файл класса с помощью загрузчика классов

Существует альтернативный подход, который использует дизайн загрузчика классов Java и работает без генерации дополнительных классов.

В Java есть иерархия загрузчиков классов. У каждого загрузчика классов есть родительский загрузчик классов. Корнем иерархии загрузчика классов является загрузчик классов загрузки. Когда класс загружается с загрузчиком классов, он пытается загрузить класс сначала с загрузчиком родительского класса, а затем сам.

Вы можете загрузить тестовый класс с помощью загрузчика текущего класса. Jar это и загрузить его с вашим собственным загрузчиком классов. Единственное отличие состоит в том, что вы устанавливаете загрузчик родительского класса на тот, который не может загрузить ваш тестовый класс.

String resource = My.class.getName().replace(".", "/") + ".class";

//class loader of your test class
ClassLoader myClassLoader = currentThread().getContextClassLoader();
assert ! toList(myClassLoader.getResources(resource)).isEmpty();

//just to be sure that the resource cannot be loaded from the parent classloader
ClassLoader parentClassloader = getSystemClassLoader().getParent();
assert toList(parentClassloader.getResources(resource)).isEmpty();

//your class loader
URLClassLoader myLoader = new URLClassLoader(new URL[0], parentClassloader);
assert toList(myLoader.getResources(resource)).isEmpty();
0 голосов
/ 10 сентября 2009

Maven разрешает порядок сборки с помощью анализа зависимостей, поэтому обычно ваши JAR будут собираться по порядку, потому что тот, который использует ваши тестовые JAR, просто объявляет их как зависимости. Однако зависимости также размещаются на пути к классам. «Область действия» зависимости определяет, по какому пути к классам она идет. Например, зависимости 'compile' находятся в пути к классам для компиляции, тестирования и запуска; зависимости «времени выполнения» находятся в пути к классам для тестирования и запуска; 'test' зависимости находятся только на пути к классам во время теста. К сожалению, у вас есть случай, который не охватывается ни одной из доступных областей: у вас есть зависимость, но вы не хотите, чтобы она находилась в пути к классам. Это ограниченный вариант использования, и поэтому у вас возникают проблемы с поиском примеров.

Итак, если какой-то гуру Maven не встанет, чтобы указать обратное, я полагаю, что это невозможно без написания специального плагина Maven. Вместо этого, однако, я рекомендую что-то еще. Вам действительно нужны специально созданные JAR-файлы для тестирования вашего загрузчика классов? Это звучит подозрительно для меня. Возможно, вы можете использовать любой старый JAR? Если это так, я бы использовал плагин maven-dependency-plugin, чтобы скопировать JAR, о котором известно, что он всегда находится в вашем хранилище (например, log4j), в целевой каталог вашего локального модуля. Затем ваш тест может получить доступ к этому JAR через filepath по номеру target/log4j-xxx.jar, и вы сможете делать свое дело.

...