Skip to content

JEE: Arquillian

2014 April 27
by Haf

Überblick

Arquillian ist ein Framework für Integration Tests. Es bietet die Möglichkeit für bestimmte Testfälle ein Deployment bereitzustellen, was die nur die relevanten Klassen besitzt. Diese sogenannten Micro-Deployments können mittels Arquillian einfach definiert werden und dann in einem embedded or existierenden Container eingesetzt werden. In diesem werden dann die Testfälle durchgeführt. Zur Vollständigkeit ist noch erwähnt, dass Arquillian auch für client-seitige Tests verwendet werden kann, in solchen Fällen ist ein Deployment nicht notwendig.
Als Deployment-Format stehen verschiedene zur Verfügung, z.B. Jar, War, Ear etc.
Genauso stehen als Container verschiedene Alternativen zur Verfügung. Arquillian bietet hierfür die gängigsten Adapter an, siehe [2].

 

Einrichten

Die Einrichtung ist recht simple, und u.a. hier [1] sehr gut erklärt. Nach der Anpassung der pom.xml kann es schon losgehen:

Zu beachten ist, dass wegen einem Bug in dem alten Surefire Plugin es zu Problem mit der Nutzung von Arquillian kommen kann. Dabei wird der Container nicht sauber beendet. Dies ist in aktuelleren Surefire Plugins behoben.

Die wichtigsten Punkte für den erfolgreichen Einsatz:

  • Testklasse mit @RunWith(Arquillian.class) annotieren
  • Public static Methode mit @Deployment erstellen, welches das Deployment (org.jboss.shrinkwrap.api.ShrinkWrap)
  • Test-Methoden (mit @Test)

Testfälle

Anbei folgen verschiedene Testfälle, die heute nur Java-Archive beachten. Komplexere Deployments werden in einem nachfolgenden Beitrag beschrieben.

Java-Archive und POJO

Im Projekt gibt es eine einfache Java Util-Klasse OneUtils, welche für die ersten Tests verwendet werden soll.

Die Test-Klasse hierfür sie wie folgt aus:

Das erstellte Deployment (hier Jar) soll nur die OneUtils-Klasse. Im dem Testfall wird diese Klasse auch gleich durch die Injezierung verwendet. Die Test-Methode prüft hier nur, ob das Objekt existiert.
Nach Ausführung dieses JUnit-Testfalls wird der Inhalt des Jars ausgegeben und die Test-Methode ausgeführt. Output sieht etwa wie folgt aus:

[code]
3a4df341-1026-42e4-ac33-c9200f17acd8.jar:
/com/
/com/haddouti/
/com/haddouti/pg/
/com/haddouti/pg/jee6/
/com/haddouti/pg/jee6/util/
/com/haddouti/pg/jee6/util/OneUtils.class
111 [main] INFO org.jboss.weld.Version – WELD-000900 1.1.5 (Final)
1398533984836
[/code]

Wie man sehen kann, wird der Name der Jar-Datei dynamisch vergeben. Als Container wird der aktuell konfigurierte verwendet und das ist gerade: Weld EE embedded.
Natürlich kann hier auch mvn test verwendet werden, dann wird auch das Surefire Plugin verwendet.

Git Tag: JEE-Testapp-01

Java-Archive und CDI

Im folgenden Beispiel werden mehr CDI Klassen verwendet, mit einer Beziehung zueinander. So können wir auch sehen, dass Arquillian die Klassen richtig mit CDI initialisiert.

OneService greift auf OneStatelessBean so dass in der process()-Methode auch die process()-Methode von OneStatelessBean verwendet wird. Die Klassen sind nicht annotiert, da im CDI-Umfeld dies nicht notwendig ist. Die Injezierung geschieht mittels Inject.
Die Test-Klasse für ein Jar-Archive sieht wie folgt aus:

Die Ausführung liefert u.a. folgendes:
[code]
d97a6ce3-943b-4377-8e41-94968459a99b.jar:
/com/
/com/haddouti/
/com/haddouti/pg/
/com/haddouti/pg/jee6/
/com/haddouti/pg/jee6/service/
/com/haddouti/pg/jee6/service/OneStatelessBean.class
/com/haddouti/pg/jee6/OneService.class
/META-INF/
/META-INF/beans.xml
125 [main] INFO org.jboss.weld.Version – WELD-000900 1.1.5 (Final)
init(): OneStatelessBean
init(): OneService
OneService.OneStatelessBean@11576309
[/code]

Git Tag: JEE-Testapp-02

Java-Archive und EJB

Im folgenden Testfall wollen wir EJB verwenden, d.h. @Stateless und @EJB statt @Inject. Hierfür reicht jedoch der aktuell verwendete Weld Container nicht aus. Da Arquillian verschiedene andere Container unterstützt, ersetzen wir den aktuellen Container einen richtigen Application Server, jetzt durch Glassfish Embedded. Dafür muss in der pom.xml die Abhängigkeiten zu Weld durch die für Glassfish Embedded ersetzt werden. Zusätzlich muss auch die JEE-API entfernt werden, da dies Glassfish schon mitliefert.

Nach der minimalen Anpassung des Testfalls (@Inject durch @EJB) läuft der Testfall sauber durch:

Die Ausgabe ist jetzt umfangreicher, da Glassfish gestartet wird. Auszugweise sieht das etwa wie folgt aus:
[code]
26.04.2014 22:09:19 com.sun.enterprise.v3.server.CommonClassLoaderServiceImpl findDerbyClient
INFO: Cannot find javadb client jar file, derby jdbc driver will not be available by default.
26.04.2014 22:09:20 org.hibernate.validator.util.Version
INFO: Hibernate Validator 4.2.0.Final
….
INFO: Grizzly Framework 1.9.46 started in: 274ms – bound to [0.0.0.0:8181]
26.04.2014 22:09:23 com.sun.enterprise.v3.server.AppServerStartup run
INFO: GlassFish Server Open Source Edition 3.1.2 (java_re-private) startup time : Embedded (2.959ms), startup services(2.361ms), total(5.320ms)
26.04.2014 22:09:24 org.glassfish.admin.mbeanserver.JMXStartupService$JMXConnectorsStarterThread run
INFO: JMX006: JMXStartupService had disabled JMXConnector system
5ac8c374-a454-4378-9a3c-82f17b2e5129.jar:
/com/
/com/haddouti/
/com/haddouti/pg/
/com/haddouti/pg/jee6/
/com/haddouti/pg/jee6/service/
/com/haddouti/pg/jee6/service/OneStatelessBean.class
/com/haddouti/pg/jee6/OneService.class
/META-INF/
/META-INF/beans.xml
26.04.2014 22:09:29 com.sun.ejb.containers.EjbContainerUtilImpl createThreadPoolExecutor
INFO: Created EjbThreadPoolExecutor with thread-core-pool-size 16 thread-max-pool-size 32 thread-keep-alive-seconds 60 thread-queue-capacity 2147483647 allow-core-thread-timeout false

INFO: WEB0172: Virtual server [server] loaded default web module []
classLoader = WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@13cb2c6
26.04.2014 22:09:36 com.sun.ejb.containers.BaseContainer initializeHome
INFO: EJB5181:Portable JNDI names for EJB OneService: [java:global/test/OneService!com.haddouti.pg.jee6.OneService, java:global/test/OneService]
26.04.2014 22:09:37 com.sun.ejb.containers.BaseContainer initializeHome
INFO: EJB5181:Portable JNDI names for EJB OneStatelessBean: [java:global/test/OneStatelessBean!com.haddouti.pg.jee6.service.OneStatelessBean, java:global/test/OneStatelessBean]
26.04.2014 22:09:37 org.jboss.weld.bootstrap.WeldBootstrap
INFO: WELD-000900 SNAPSHOT
26.04.2014 22:09:41 com.sun.enterprise.web.WebApplication start
INFO: WEB0671: Loading application [test] at [/test]
26.04.2014 22:09:41 org.glassfish.deployment.admin.DeployCommand execute
INFO: test was successfully deployed in 14.115 milliseconds.
init(): OneService
init(): OneStatelessBean
OneService.OneStatelessBean@28967553
classLoader = WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@13cb2c6
PlainTextActionReporterSUCCESSNo monitoring data to report.
26.04.2014 22:09:44 org.glassfish.admin.mbeanserver.JMXStartupService shutdown
INFO: JMX001: JMXStartupService and JMXConnectors have been shut down.
26.04.2014 22:09:44 com.sun.enterprise.v3.server.AppServerStartup stop
INFO: Shutdown procedure finished
26.04.2014 22:09:44 AppServerStartup run
INFO: [Thread[GlassFish Kernel Main Thread,5,main]] exiting
[/code]

Git Tag: JEE-Testapp-03

Verschiedene Container

Eins der Stärken von Arquillian ist die Unterstützung verschiedener Container. Um verschiedene Container zu unterstützten, empfiehlt es sich, diese mit Maven Profile zu realisieren. Exemplarisch erstellen wir drei Profile für Weld, Glassfish Embedded und WildFly Embedded. Bzgl. WildFly Embedded ist die Bezeichnung etwas irreführend. Da mit WildFly Embedded die Standalone Application Server in derselben JVM gestartet wird, wie die Test-Fälle auch [3]. Weiter muss noch das Systemproperty gesetzt werden „-Djava.util.logging.manager=org.jboss.logmanager.LogManager“. Ob hier noch eine richtige Embedded-Version kommt, ist unklar. Ein Auszug des pom.xml sieht dann wie folgt aus:

Zu beachten ist, dass WildFly 8 Java Version 7 erwartet. Zusätzlich benötigt es den Parameter jbossHome, mit einem Verweis auf das Verzeichnis wo der Application Server installiert ist. Dies wird in src/test/resources/arquillian.xml hinterlegt:

Dadurch dass jetzt Profile hinterlegt sind, und die notwendigsten Abhängigkeiten in den einzelnen Profilen hinterlegt sind, existieren nun Compiler-Fehler. Dies kann behoben werden, wenn in Eclipse/Maven ein Profil als Standard ausgewählt wird. Entweder direkt in dem Profil durch activation > activeByDefault = true oder in dem in Project properties > Maven > Active Maven profiles explizit ein Profil angegeben wird.
Für WildFly steht ein RunConfig zur Verfügung, der noch den Jboss LogManager setzt.
Wie man sehen kann, lassen sich verschiedene Container leicht mit Arquillian einbinden. WildFly ist noch recht frisch, so dass hier zu hoffen ist, dass zukünftig die Nutzung genauso einfach funktioniert wie bei den anderen Containern.

Git Tag: JEE-Testapp-04
Git: git://git.schokokeks.org/playground.git
Project: testapp-jee6

Referenzen

[1] Arquillian Getting started http://arquillian.org/guides/getting_started/
[2] http://arquillian.org/modules/
[3] https://community.jboss.org/message/855086#855086
[4] http://arquillian.org/modules/wildfly-arquillian-wildfly-embedded-container-adapter/
[5] http://arquillian.org/modules/arquillian-glassfish-embedded-3.1-container-adapter/
[6] http://arquillian.org/modules/arquillian-weld-ee-embedded-1.1-container-adapter/

Share it!
  •  
  •  
  •  
  •  
  •  
  •  
No comments yet

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS