Einführung in das Testen mit Arquillian

1. Übersicht

Arquillian ist ein containerunabhängiges Integrationstest-Framework für Jakarta EE. Die Verwendung von Arquillian minimiert den Aufwand für die Verwaltung von Containern, Bereitstellungen, Framework-Initialisierungen usw.

Wir können uns darauf konzentrieren, tatsächliche Tests zu schreiben und nicht die Testumgebung zu booten.

2. Kernkonzepte

2.1. Bereitstellungsarchive

Es gibt eine einfache Möglichkeit, unsere Anwendung zu testen, wenn sie in einem Container ausgeführt wird.

Erstens bietet die ShrinkWrap- Klasse eine API zum Erstellen von bereitstellbaren * .jar- , * .war- und * .ear- Dateien.

Anschließend können wir mit Arquillian die Testbereitstellung mithilfe der Annotation @Deployment konfigurieren - für eine Methode, die ein ShrinkWrap- Objekt zurückgibt .

2.2. Behälter

Arquillian unterscheidet drei verschiedene Arten von Behältern:

  • Remote-Test mit einem Remote-Protokoll wie JMX
  • Verwaltet - Remote-Container, deren Lebenszyklus jedoch von Arquillian verwaltet wird
  • Eingebettet - lokale Container, in denen Tests mit lokalen Protokollen durchgeführt werden

Wir können Container auch nach ihren Fähigkeiten klassifizieren:

  • Jakarta EE-Anwendungen, die auf einem Anwendungsserver wie Glassfish oder JBoss bereitgestellt werden
  • Servlet-Container, die auf Tomcat oder Jetty bereitgestellt werden
  • Standalone-Container
  • OSGI-Container

Es untersucht den Laufzeitklassenpfad und wählt automatisch den verfügbaren Container aus.

2.3. Testanreicherung

Arquillian bereichert Tests, indem es z. B. die Abhängigkeitsinjektion bereitstellt, damit wir unsere Tests leicht schreiben können.

Wir können Abhängigkeiten mit @Inject einfügen , Ressourcen mit @Resource einfügen , EJB-Session-Beans mit @EJB usw.

2.4. Mehrere Testläufer

Mit der Anmerkung können mehrere Bereitstellungen erstellt werden:

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

Wobei der Name der Name der Bereitstellungsdatei und der Parameter order die Ausführungsreihenfolge der Bereitstellung ist, können wir jetzt mithilfe der Anmerkung folgende Tests für mehrere Bereitstellungen gleichzeitig ausführen:

@Test @OperateOnDeployment("myname")

Der Vorher-Test wird für den Bereitstellungscontainer myname in der in der Annotation @Deployment definierten Reihenfolge ausgeführt .

2.5. Arquillian Extensions

Arquillian bietet mehrere Erweiterungen an, falls unsere Testanforderungen nicht durch die Kernlaufzeit abgedeckt werden. Wir haben Persistenz, Transaktionen, Client / Server, REST-Erweiterungen usw.

Wir können diese Erweiterungen aktivieren, indem wir den Maven- oder Gradle-Konfigurationsdateien entsprechende Abhängigkeiten hinzufügen.

Häufig verwendete Erweiterungen sind Drone, Graphen und Selen.

3. Maven-Abhängigkeiten und Setup

Fügen wir unserer Datei pom.xml die folgende Abhängigkeit hinzu :

 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 

Die neueste Version der Abhängigkeiten finden Sie hier: arquillian-bom, org.glassfish.main.extras, org.jboss.arquillian.container.

4. Einfacher Test

4.1. Erstellen Sie eine Komponente

Beginnen wir mit einer einfachen Komponente. Wir fügen hier keine erweiterte Logik ein, um uns auf Tests konzentrieren zu können:

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

Mit Arquillian möchten wir testen, ob sich diese Klasse beim Aufrufen als CDI-Bean korrekt verhält.

4.2. Schreiben Sie unseren ersten Arquillian-Test

Zunächst müssen wir angeben, dass unsere Testklasse mit dem Framework-spezifischen Runner ausgeführt werden soll:

@RunWith(Arquillian.class) 

Wenn wir unsere Tests in einem Container ausführen möchten , müssen wir die Annotation @Deployment verwenden .

Arquillian verwendet nicht den gesamten Klassenpfad, um das Testarchiv zu isolieren. Stattdessen wird die ShrinkWrap- Klasse verwendet, eine Java-API zum Erstellen von Archiven. Wenn wir das zu testende Archiv erstellen, geben wir an, welche Dateien in den Klassenpfad aufgenommen werden sollen, um den Test zu verwenden. Während der Bereitstellung isoliert ShrinkWrap nur die für den Test erforderlichen Klassen.

Mit der Methode addclass () können wir alle erforderlichen Klassen angeben und eine leere Manifestressource hinzufügen.

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()); }

In diesem Test erstellen wir zunächst vier Fahrzeuginstanzen und überprüfen, ob die Anzahl der Zeilen in der Datenbank der von uns erstellten entspricht.

8. Fazit

In diesem Tutorial haben wir:

  • Einführung der arquillianischen Kernkonzepte
  • injizierte eine Komponente in den Arquillian-Test
  • testete einen EJB
  • getestete Persistenz
  • führte den Arquillian-Test mit Maven durch

Sie finden den Code aus dem Artikel auf Github.