Статьи

Arquillian на старых серверах

В большинстве случаев, когда что-то не работает, вы просто гуглите ошибку и в основном все готово. Хорошая особенность работы в организациях, которые отстают в технологическом отношении, заключается в том, что это, как правило, более сложная задача, и вы обязаны быть креативными. Я застрял на JBoss 5.1 EAP, но это не мешает мне использовать современный подход в разработке программного обеспечения. В области качества одной из таких попыток является предоставление моим разработчикам способа тестирования их кода в контейнере. Так как мы новички в мире EJB3это означает, что им понадобится настоящее интеграционное тестирование. Учитывая стеки, доступные на момент написания этой статьи, я выбрал Arquillian, который кажется лучшим (и единственным?) Инструментом для достижения этой цели. С помощью этого фреймворка (а также моего верного TestNG) я был настроен на тестирование компонентов Java EE на JBoss 5.1 EAP. В этой статье описывается, как это сделать (а также упоминаются подводные камни, которые мне пришлось преодолеть).

 

Arquillian основы

В основном Arquillian предоставляет разработчикам возможность управлять жизненным циклом сервера приложений и развертывать на нем артефакт JavaEE, автоматически и интегрируя его с вашим любимым механизмом тестирования (читайте TestNG — или JUnit, если необходимо). Архитектура Arquillian основана на универсальном движке и адаптерах для конкретных серверов приложений. Если для вашего сервера приложений нет доступных адаптеров, это не повезло. Если вы чувствуете себя игривым, попробуйте поискать адаптер WebSphere … разработанный. Первая трудность заключалась в том, что во время моей работы не было адаптера JBoss EAP 5.1, но я прочитал из Интернета, что он находится между 5,0 ГА и 6,0 ГА: произошел длительный процесс проб и ошибок (сейчас, есть хоть
какая-то документацияСпасибо, ребята из Arquillian, которые услышали мою просьбу в Твиттере — спасибо!). Типа сервера и его версии недостаточно, чтобы получить нужный адаптер, вам также нужно будет выбрать способ взаимодействия с сервером приложений:

  • Встроенный: вы загружаете все зависимости, обеспечивает конфигурацию и готовность, Arquillian волшебным образом создает работающий встроенный сервер приложений. Pro: вам не нужно устанавливать сервер приложений на каждый компьютер разработчика; минусы: настройка может быть кошмаром, и с конечной платформой могут быть огромные различия, что отрицательно сказывается на цели интеграционного тестирования.
  • Удаленный: использовать существующий и работающий сервер приложений. Разумно выбирайте между выделенным сервером для всех разработчиков (которые будут использовать одну и ту же конфигурацию, но также и одинаковые ресурсы) и одним сервером приложений для каждого разработчика (кто сказал, что кошмар maintenace?).
  • Управляется: так же, как удаленный, но тесты запускают и останавливают сервер. Лучше подходит для одного сервера приложений на разработчика.
  • Местный: я нашел следы этого, хотя он, кажется, похоронен глубоко. Кажется, что это то же самое, что и управляемый, но он использует файловую систему вместо проводной для выполнения своей работы (запуск / остановка с помощью вызова сценариев, развертывание путем копирования архивов в ожидаемое местоположение, …), таким образом, термин локальный.

Каждый адаптер можно настроить в соответствии с вашими потребностями через файл arquilian.xml. Для пользователей Maven это происходит в корне src / test / resources. Не волнуйтесь, каждый адаптер точно документирован для параметров конфигурации. Моя выглядит так:

 

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <container qualifier="jboss" default="true">
        <configuration>
            <property name="javaHome">${jdk.home}</property>
            <property name="jbossHome">${jboss.home}</property>
            <property name="httpPort">8080</property>
            <property name="rmiPort">1099</property>
            <property name="javaVmArguments">-Xmx512m -Xmx768m -XX:MaxPermSize=256m
                -Djava.net.preferIPv4Stack=true
                -Djava.util.logging.manager=org.jboss.logmanager.LogManager
                -Djava.endorsed.dirs=${jboss.home}/lib/endorsed
                -Djboss.boot.server.log.dir=${jboss.home}
                -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
            </property>
        </configuration>
    </container>
</arquillian

Наконец, сам тестовый класс должен расширять org.jboss.arquillian.testng.Arquillian (или, если вы придерживаетесь JUnit, используйте @RunWith). В следующем фрагменте показан пример тестового класса TestNG с использованием Arquillian:

public class WebIT extends Arquillian {

    @Test
    public void testMethod() { ... }

    @Deployment
    public static WebArchive createDeployment() { ... }
}

Создание архива

Тактика Arquillian в отношении тестирования в контейнере заключается в развертывании только того, что вам нужно. Таким образом, он поставляется с инструментом под названием ShrinkWrap, который позволяет упаковывать только соответствующие части того, что должно быть проверено. Например, в следующем примере создается архив с именем web-test.war, связывающий класс ListPersonServlet и дескриптор веб-развертывания. Более расширенное использование будет включать библиотеки.

WebArchive archive = ShrinkWrap.create(WebArchive.class, "web-test.war")
    .addClass(ListPersonServlet.class)
    .setWebXML(new File("src/main/webapp/WEB-INF/web.xml"));

Платформа Arquillian будет искать статический метод, помеченный @Deployment, который возвращает такой архив, чтобы развернуть его на сервере приложений (через адаптер). Совет: используйте метод toString () в архиве, чтобы увидеть, что он содержит, если у вас есть ошибки.

Пирожное на мавенском пироге

Даже если вы не фанат Maven, я думаю, что этот момент заслуживает некоторого внимания. ИМХО, интеграционные тесты не должны быть частью процесса сборки, так как они по своей природе более хрупки: простая ошибка конфигурации на сервере приложений и ваша сборка завершается неудачно без реальной причины. Таким образом, я бы рекомендовал поместить ваши тесты в отдельный модуль, который не вызывается его родителем. Кроме того, я также использую плагин Maven Failsafe вместо Surefire, чтобы получить чистое разделение модульных тестов и интеграционных тестов, даже с отдельными модулями, чтобы получить разные метрики для обоих (например, в Sonar). Чтобы получить это разделение из коробки, просто убедитесь, что ваши тестовые классы заканчиваются IT (например, Integration Test). Обратите внимание, что интеграционные тесты связаны с фазой жизненного цикла интеграционных тестов непосредственно перед установкой.

Здесь идет JBoss EAP

Теперь самое сложное, фактическое развертывание на JBoss 5.1 EAP. Эта стадия, вероятно, продлится долго и потребует много времени, чтобы идти вперед и назад. Чтобы быть максимально продуктивным, первое, что нужно сделать, это найти журналы. Если вы сохранили указанные выше конфигурации, они находятся в каталоге JBoss <профиль> / logs. Если вы чувствуете, что журналы слишком многословны для ваших собственных вкусов (я так и сделал), просто измените приоритет root с $ {jboss.server.log.threshold} на INFO в файле <profile> /conf/jboss-log4j.xml. На моей машине я продолжал получать ошибки порта привязки JVM. Таким образом, я изменил порт виновного соединителя в файле server.xml (FYI, это был соединитель AJP, и JBoss прекратил жаловаться, когда я изменил 8009 на 8010). Последний шаг для EAP — отключение безопасности. Поскольку он ориентирован на предприятия, в EAP по умолчанию включена защита:в контексте тестирования я не заботился об аутентификации для развертывания моих артефактов. Откройте файл конфигурации <profile> /deploy/profileservice-jboss-beans.xml и выполните поиск «закомментируйте этот список, чтобы отключить проверки подлинности для службы профиля». Делайте, как вам говорят ? В качестве альтернативы, вы также можете пройти сложный путь и настроить аутентификацию: подробные инструкции доступны
страница адаптера .

Делать вещи самостоятельно

До этого момента мы более или менее следовали инструкциям здесь и там. Теперь мы должны запятнать наши ногти и использовать немного нашего серого вещества.

  • Первое, на что нужно обратить внимание — это странное java.lang.IllegalStateException при запуске теста. Как ни странно, это вызвано тем, что в Arquillian отсутствуют некоторые библиотеки, которые должны быть ShrinkWrapped вместе с вашим реальным кодом. В моем случае мне понадобился следующий фрагмент моего веб-архива:
    MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class);
    archive.addAsLibraries(
        resolver.artifact("org.jboss.arquillian.testng:arquillian-testng-container:1.0.0.Final")
                .artifact("org.jboss.arquillian.testng:arquillian-testng-core:1.0.0.Final")
                .artifact("org.testng:testng:6.5.2").resolveAsFiles());
  • Следующая ошибка гораздо более зловещая и проистекает из внутренней работы Аркиллиана.
    java.util.NoSuchElementException
        at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:375)
        at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:384)
        at org.jboss.arquillian.container.test.spi.util.TestRunners.getTestRunner(TestRunners.java:60)

    Когда вы посмотрите на код, вы увидите, что Arquillian использует функцию поставщика услуг (дополнительную информацию см. Здесь ). Но, к моему большому огорчению, он не настраивает реализацию, которую должен использовать сервис org.jboss.arquillian.container.test.spi.TestRunner и, следовательно, терпит неудачу. Мы должны создать такую ​​конфигурацию вручную: файл должен содержать только org.jboss.arquillian.testng.container.TestNGTestRunner (такова сила поставщика услуг). Не забудьте упаковать его вместе с архивом, чтобы иметь какой-либо шанс на успех:

    archive.addAsResource(new File("src/test/resources/META-INF/services"), "META-INF/services");

Обновление [28 мая] : две вышеуказанные точки могут быть отменены, если вы используете правильную зависимость Maven (Arquillian BOM). Проверьте POM в прикрепленном проекте .

В конце все должно работать нормально, кроме финального журнала сообщений в тесте: Завершение работы сервера: по умолчанию Запись дампа потока сервера в /path/to/jboss-as/server/default/log/threadDump.logЭто означает, что Arquillian не может завершить работу сервер, потому что он не может аутентифицироваться. Это не будет иметь никаких последствий, но помечает тест как неудачный и, следовательно, требует исправления. Отредактируйте файл <profile> /conf/props/jmx-console-users.properties и раскомментируйте строку admin = admin.

Вывод

Все предыдущие шаги заняли у меня около половины рабочей недели (кажется, я более продуктивен, когда не работаю полный рабочий день, так как мой мозг запускает некоторые фоновые потоки для решения проблем). Это было нелегко, но я горжусь, что победил эту чертову штуку. Более того, несколько проприетарных параметров конфигурации были опущены в этой статье. В заключение, Arquillian, кажется, является хорошей средой для тестирования в контейнере, но, похоже, ее нужно отточить по углам: я думаю, что использование TestNG может быть культовым объектом здесь. Вы можете найти источники для этой статьи
здесь , в формате Eclipse / Maven. Чтобы идти дальше: