Въведение в тестването с Arquillian

1. Общ преглед

Arquillian е рамка за тестване на агностични контейнери за Джакарта EE. Използването на Arquillian минимизира тежестта от управлението на контейнери, разполагания, инициализации на рамки и т.н.

Можем да се съсредоточим върху писането на действителни тестове, а не върху зареждането на тестовата среда.

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

2.1. Архиви за разполагане

Има лесен начин за тестване на нашето приложение, когато работи в контейнер.

Първо, класът ShrinkWrap предоставя API за създаване на разгръщащи се * .jar, * .war и * .ear файлове.

След това Arquillian ни позволява да конфигурираме тестовото разполагане, използвайки анотацията @Deployment - за метод, който връща обект ShrinkWrap .

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

Arquillian разграничава три различни вида контейнери:

  • Дистанционно - тествано с помощта на отдалечен протокол като JMX
  • Управлявани - отдалечени контейнери, но техният жизнен цикъл се управлява от Arquillian
  • Вградени - локални контейнери, където тестовете се извършват с помощта на локални протоколи

Също така можем да класифицираме контейнерите по техните възможности:

  • Джакарта EE приложения, разположени на сървър за приложения като Glassfish или JBoss
  • Сервлетни контейнери, разположени на Tomcat или Jetty
  • Самостоятелни контейнери
  • OSGI контейнери

Той изследва пътя на класа на изпълнението и автоматично избира наличния контейнер.

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

Arquillian обогатява тестовете, като осигурява напр. Инжекция на зависимост, за да можем лесно да пишем тестовете си.

Можем да инжектираме зависимости, като използваме @Inject , инжектираме ресурси с @Resource , EJB сесионни компоненти, използвайки @EJB и т.н.

2.4. Множество тестови бегачи

Можем да създадем множество разполагания с помощта на анотацията:

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

Където името е името на файла за внедряване, а параметърът за поръчка е редът за изпълнение на внедряването, така че вече можем да изпълняваме тестове на множество разполагания едновременно, като използваме анотацията:

@Test @OperateOnDeployment("myname")

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

2.5. Arquillian Extensions

Arquillian предлага множество разширения, в случай че нуждите ни от тестване не са покрити от основната среда на изпълнение. Имаме постоянство, транзакции, клиент / сървър, REST разширения и т.н.

Можем да активираме тези разширения, като добавим подходящи зависимости към конфигурационните файлове на Maven или Gradle.

Често използвани разширения са Drone, Graphene и Selenium.

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

Нека добавим следната зависимост към нашия файл pom.xml :

 org.jboss.arquillian arquillian-bom 1.1.13.Final import pom   org.glassfish.main.extras glassfish-embedded-all 4.1.2 test   org.jboss.arquillian.container arquillian-glassfish-embedded-3.1 1.0.0.Final test 

Най-новата версия на зависимостите може да бъде намерена тук: 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 () , можем да посочим всички необходими класове и да добавим празен ресурс на манифест.

The JavaArchive.class creates a mockup web archive called test.war, this file is deployed into the container and then is used by Arquillian to perform tests:

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

Then we inject our component in the test:

@Inject private Component component;

Finally, we perform our test:

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

5. Testing Enterprise Java Beans

5.1. Enterprise Java Bean

With Arquillian we can test dependency injection of an Enterprise Java Bean, to do that we create a class that has a method for converting any word to lowercase:

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

Using this class, we create a stateless class for calling the method created before:

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

The CapsConvertor class gets injected into a service bean:

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

5.2. Test the Enterprise Java Bean

Now we can use Arquillian to test our enterprise Java Bean, injecting the CapsService:

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

Using ShrinkWrap, we ensure that all classes are wired correctly:

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

6. Testing JPA

6.1. Persistence

We can also use Arquillian to test persistence. First, we are going to create our entity:

@Entity public class Car { @Id @GeneratedValue private Long id; @NotNull private String name; // getters and setters }

We have a table that holds names of cars.

Then we are going to create our EJB to perform basic operations on our data:

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

With saveCar we can save the car names into the database, we can get all cars stored with findAllCars, and also we can delete a car from the database with deleteCar.

6.2. Test Persistence With Arquillian

Now we can perform some basic tests using Arquillian.

First, we add our classes to our ShrinkWrap:

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

Then we create our test:

@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
  • инжектира компонент в теста на Аркилиан
  • тествал EJB
  • тествана упоритост
  • извършил теста на Аркилиан с помощта на Maven

Можете да намерите кода от статията в Github.