«1. Обзор

Arquillian — это среда тестирования интеграции, не зависящая от контейнера, для Jakarta EE. Использование Arquillian сводит к минимуму нагрузку на управление контейнерами, развертыванием, инициализацией фреймворка и т. д.

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

2. Основные понятия

2.1. Архивы развертывания

Существует простой способ тестирования нашего приложения при работе внутри контейнера.

Во-первых, класс ShrinkWrap предоставляет API для создания развертываемых файлов *.jar, *.war и *.ear.

Затем Arquillian позволяет нам настроить тестовое развертывание с помощью аннотации @Deployment для метода, который возвращает объект ShrinkWrap.

2.2. Контейнеры

Arquillian различает три разных типа контейнеров:

    Удаленные — тестируются с использованием удаленного протокола, такого как JMX Управляемые — удаленные контейнеры, но их жизненный цикл управляется Arquillian Embedded — локальные контейнеры, в которых тесты выполняются с использованием локальные протоколы

Кроме того, мы можем классифицировать контейнеры по их возможностям:

    Приложения Jakarta EE, развернутые на сервере приложений, таком как Glassfish или JBoss Контейнеры сервлетов, развернутые на автономных контейнерах Tomcat или Jetty Контейнеры OSGI

Он проверяет путь к классам во время выполнения и автоматически выбирает доступный контейнер.

2.3. Обогащение тестов

Arquillian обогащает тесты, предоставляя, например, внедрение зависимостей, чтобы мы могли легко писать наши тесты.

Мы можем вводить зависимости с помощью @Inject, вводить ресурсы с помощью @Resource, сеансовые компоненты EJB с помощью @EJB и т. д.

2.4. Multiple Test Runners

Мы можем создать несколько развертываний, используя аннотацию:

@Deployment(name="myname" order = 1)

Где имя — это имя файла развертывания, а параметр порядка — порядок выполнения развертывания, поэтому теперь мы можем запускать тесты на несколько развертываний одновременно с использованием аннотации:

@Test @OperateOnDeployment("myname")

Тест before выполняется в контейнере развертывания myname в порядке, определенном в аннотации @Deployment.

2.5. Расширения Arquillian

Arquillian предлагает несколько расширений на случай, если наши потребности в тестировании не покрываются основной средой выполнения. У нас есть постоянство, транзакции, клиент/сервер, расширения REST и т. д.

Мы можем включить эти расширения, добавив соответствующие зависимости в файлы конфигурации Maven или Gradle.

Обычно используются расширения Drone, Graphene и Selenium.

3. Зависимости и настройка Maven

Давайте добавим следующую зависимость в наш файл pom.xml:

<dependency>
    <groupId>org.jboss.arquillian</groupId>
    <artifactId>arquillian-bom</artifactId>
    <version>1.1.13.Final</version>
    <scope>import</scope>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>org.glassfish.main.extras</groupId>
    <artifactId>glassfish-embedded-all</artifactId>
    <version>4.1.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.jboss.arquillian.container</groupId>
    <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
    <version>1.0.0.Final</version>
    <scope>test</scope>
</dependency>

Последнюю версию зависимостей можно найти здесь: arquillian-bom, org.glassfish.main .extras, org.jboss.arquillian.container.

4. Простой тест

4.1. Создание компонента

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

public class Component {
    public void sendMessage(PrintStream to, String msg) {
        to.println(message(msg));
    }

    public String message(String msg) {
        return "Message, " + msg;
    }
}

Используя Arquillian, мы хотим проверить, правильно ли ведет себя этот класс при вызове в качестве компонента CDI.

4.2. Напишем наш первый арквиллианский тест

Во-первых, нам нужно указать, что наш тестовый класс должен запускаться с использованием специфичного для фреймворка раннера:

@RunWith(Arquillian.class)

Если мы собираемся запускать наши тесты внутри контейнера, нам нужно используйте аннотацию @Deployment.

Arquillian не использует весь путь к классам для изоляции тестового архива. Вместо этого он использует класс ShrinkWrap, который представляет собой Java API для создания архивов. Когда мы создаем архив для тестирования, мы указываем, какие файлы включать в путь к классам для использования теста. Во время развертывания ShrinkWrap изолирует только те классы, которые необходимы для теста.

С помощью метода addclass() мы можем указать все необходимые классы, а также добавить пустой ресурс манифеста.

Класс JavaArchive.class создает макет веб-архива с именем test.war, этот файл развертывается в контейнере, а затем используется Arquillian для выполнения тестов:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClass(Component.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

Затем мы внедряем наш компонент в тест: ~ ~~

@Inject
private Component component;

Наконец, мы выполняем наш тест:

assertEquals("Message, MESSAGE",component.message(("MESSAGE")));
 
component.sendMessage(System.out, "MESSAGE");

5. Тестирование Enterprise Java Beans

5.1. Корпоративный Java-бин

«С помощью Arquillian мы можем протестировать внедрение зависимостей Enterprise Java Bean, для этого мы создадим класс, который имеет метод для преобразования любого слова в нижний регистр:

public class ConvertToLowerCase {
    public String convert(String word){
        return word.toLowerCase();
    }
}

Используя этот класс, мы создаем класс без состояния для вызова метода создано ранее:

@Stateless
public class CapsConvertor {
    public ConvertToLowerCase getLowerCase(){
        return new ConvertToLowerCase();
    }
}

Класс CapsConvertor внедряется в сервисный компонент:

@Stateless
public class CapsService {
 
    @Inject
    private CapsConvertor capsConvertor;
    
    public String getConvertedCaps(final String word){
        return capsConvertor.getLowerCase().convert(word);
    }
}

5.2. Тестирование корпоративного Java-бина

Теперь мы можем использовать Arquillian для тестирования нашего корпоративного Java-бина, внедрив CapsService:

@Inject
private CapsService capsService;
    
@Test
public void givenWord_WhenUppercase_ThenLowercase(){
    assertTrue("capitalize".equals(capsService.getConvertedCaps("CAPITALIZE")));
    assertEquals("capitalize", capsService.getConvertedCaps("CAPITALIZE"));
}

Используя ShrinkWrap, мы обеспечиваем правильное подключение всех классов:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClasses(CapsService.class, CapsConvertor.class, ConvertToLowerCase.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

6. Тестирование JPA

6.1. Настойчивость

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

@Entity
public class Car {
 
    @Id
    @GeneratedValue
    private Long id;
 
    @NotNull
    private String name;

    // getters and setters
}

У нас есть таблица, в которой хранятся названия автомобилей.

Затем мы собираемся создать наш EJB для выполнения основных операций с нашими данными:

@Stateless
public class CarEJB {
 
    @PersistenceContext(unitName = "defaultPersistenceUnit")
    private EntityManager em;
 
    public Car saveCar(Car car) {
        em.persist(car);
        return car;
    }
 
    public List<Car> findAllCars() {
    Query query 
      = em.createQuery("SELECT b FROM Car b ORDER BY b.name ASC");
    List<Car> entries = query.getResultList();
    
    return entries == null ? new ArrayList<>() : entries;    
 
    public void deleteCar(Car car) {
        car = em.merge(car);
        em.remove(car);
    }
}

С помощью saveCar мы можем сохранить названия автомобилей в базе данных, мы можем получить все автомобили, сохраненные с помощью findAllCars, а также мы можем удалить автомобиль из базы данных с помощью deleteCar.

6.2. Проверка постоянства с помощью Arquillian

Теперь мы можем выполнить некоторые базовые тесты с помощью Arquillian.

Сначала мы добавляем наши классы в нашу ShrinkWrap:

.addClasses(Car.class, CarEJB.class)
.addAsResource("META-INF/persistence.xml")

Затем мы создаем наш тест:

@Test
public void testCars() {
    assertTrue(carEJB.findAllCars().isEmpty());
    Car c1 = new Car();
    c1.setName("Impala");
    Car c2 = new Car();
    c2.setName("Lincoln");
    carEJB.saveCar(c1);
    carEJB.saveCar(c2);
 
    assertEquals(2, carEJB.findAllCars().size());
 
    carEJB.deleteCar(c1);
 
    assertEquals(1, carEJB.findAllCars().size());
}

В этом тесте мы сначала создаем четыре экземпляра автомобиля и проверяем, что количество строк в базе то же самое, что мы создали.

8. Заключение

В этом руководстве мы:

    представили основные концепции Arquillian, внедрили компонент в тест Arquillian, протестировали EJB, протестировали сохраняемость, выполнили тест Arquillian, используя Maven статья закончилась на Github.

«