Статьи

Один кувшин, чтобы управлять ими всеми: Arquillian + Java 8

arquillian_ui_success_256px В Java 8 реализовано много новых языковых улучшений для облегчения жизни разработчика. На мой взгляд, одна из самых замечательных особенностей Java 8 состоит в том, что в некоторых ситуациях разработанный код выглядит более красиво, чем при использовании предыдущих подходов, и я имею в виду ссылки на Lambdas и Method. Этот пост не об изучении этих функций Java 8, а о том, как применять их в платформе Arquillian .

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

Объединить библиотеки внутри JavaArchive

Для написания тестов с Arquillian вам нужно создать файл развертывания программно (jar, war или ear). Это достигается с помощью Shrinkwrap . Ваш файл развертывания иногда требует, чтобы вы добавили к нему некоторые внешние зависимости. Типичный пример — когда вы создаете WebArchive и вам нужно добавить некоторые зависимости в WEB-INF / lib . В этом случае это легко, потому что в классе WebArchive есть метод addAsLibraries, который в основном добавляет указанные файлы в путь к библиотекам.

Но что происходит, когда ваш файл развертывания является файлом JAR? Затем вам нужно объединить каждую библиотеку внутри объекта JavaArchive с помощью метода слияния .

1
2
3
4
5
6
7
private static JavaArchive mergeHibernate(JavaArchive javaArchive) {
    JavaArchive[] javaArchives = Maven.resolver().resolve("org.hibernate:hibernate-entitymanager:4.2.15.Final").withTransitivity().as(JavaArchive.class);
    for(JavaArchive hibernateDep: javaArchives) {
        javaArchive.merge(hibernateDep);
    }
    return javaArchive;
}

Это способ сделать это, но в Java 8 вы можете использовать функции foreach и ссылки на методы .

1
2
3
4
5
6
private static JavaArchive mergeHibernate(JavaArchive javaArchive) {
    JavaArchive[] javaArchives = Maven.resolver().resolve("org.hibernate:hibernate-entitymanager:4.2.15.Final").withTransitivity().as(JavaArchive.class);
    Arrays.stream(javaArchives).forEach(javaArchive::merge);
     
    return javaArchive;
}

Обратите внимание, что мы конвертируем массив в поток, чтобы мы могли вызывать функцию foreach. В версии 2.2.0 ShrinkWrap Resolver вы сможете получать зависимости в виде списка, поэтому вы сможете получить поток без какого-либо преобразования. Следующим важным моментом является то, что мы используем функцию ссылки на метод для объединения всех зависимостей. Теперь с помощью одной строки мы можем объединить все зависимости.

Создание пользовательских активов

Arquillian использует ShrinkWrap для создания файла развертывания и добавления ресурсов внутри. Эти ресурсы добавляются с помощью любого из методов, предоставляемых API, таких как add , addClass , addAsManifestReource и так далее. Эти методы могут получить в качестве первого параметра Актив . Asset — это интерфейс, который содержит только один метод openStream, который возвращает InputStream . Активы используются для настройки содержимого файла, который будет добавлен в файл развертывания.

Например:

1
archive.add(new StringAsset("My txt file"), "hello.txt");

ShrinkWrap поставляется с некоторыми уже определенными активами, такими как Url, String, Byte, Class,… но иногда вам может понадобиться реализовать свой собственный актив.

1
2
3
4
5
6
7
ShrinkWrap.create(JavaArchive.class).addAsManifestResource(
                                          new Asset() {
                                             public InputStream openStream() {
                                                  return new CheckedInputStream(urlInputStream, crc32)
                                             }
                                          },
                                     "persistence.xml");

В этом случае мы используем внутренний класс, но поскольку класс Asset можно считать функциональным интерфейсом (только один абстрактный метод), мы можем использовать Lambdas, чтобы избежать внутреннего класса.

Так много простых и удобочитаемых.

Разбор HTML-таблиц

Если вы используете Arquillian Drone или Arquillian Graphene, вы будете использовать некоторые классы WebDriver Selenium для получения элементов веб-страницы. Иногда вам нужно проверить столбцы и таблицу HTML, и в этом случае вы можете получить много шаблонного кода, повторяющегося по столбцам и строкам для проверки, содержащего правильные значения.

Ваш код до Java 8 будет выглядеть примерно так:

1
2
3
4
5
6
7
8
List<WebElement> elements = session.findElements(xpath("//table/tbody/tr/td/span[@class='title']"));
 
List<String> columnValues = new ArrayList<String>();
for(WebElement webElement : elements) {
  columnValues.add(webElement.getText());
}
 
return columnValues;

Но в Java 8 с добавлением потокового API код становится намного проще и удобочитаемее:

1
2
List<WebElement> elements = session.findElements(xpath("//table/tbody/tr/td/span[@class='title']"));
return elements.stream().map(WebElement::getText).collect(Collectors.toList());

Как видите, код довольно компактен. То, что мы делаем здесь, это в первую очередь получение всех веб-элементов заголовка колонки, никаких новостей здесь. Но тогда потоковое API вступает в игру. Сначала мы создаем поток из списка, вызывая метод stream . Затем мы вызываем метод getText из всех WebElements, представленных в списке. И, наконец, возвращается список строк, который фактически является списком содержимого всех строк заголовка столбца.

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

Итак, как вы можете видеть, Java 8 может использоваться не только в бизнес-коде, но и в тестах.