1. Arquillian in a nutshell
Copyright and all intellectual property belongs to Brockhaus Group 1
2. Preface
Targeted audience
Get the code
Why Arquillian?
The first test
Creating the archive
Create the archive using ShrinkWrap
Create the archive using maven
Configuring Arquillian
Configuring the runtime modes of arquillian
Managed container config
Embedded container config
Including persistency (extension)
Creating test data manually using a pre-filled database
Creating test data manually
Creating test data by SQL script
Creating test data by means of JSON/XML (or YML)
Some kind of round trip
Copyright and all intellectual property belongs to Brockhaus Group 2
3. Preface
This is a paper provided by Brockhaus Group for free. All
content was checked and all code was tested carefully; in
case of questions of suggestions to improve we will be happy
to receive you email at:
getKnowledge@brockhaus-group.com
Targeted audience
People interested in using Arquillian with a sound knowledge in Java EE technologies, this paper won’t
explain the details of the Java EE platform. The examples have been tested using JBoss EAP 6.1.1 and
the H2 database.
Get the code
All code used for this examples can be found here (zipped Maven project):
ftp: www.brockhaus-gruppe.de
directory: /getKnowledge/arquillian
user: ftpguest
pwd: ftpguest789
Download, unpack, you’re done
Copyright and all intellectual property belongs to Brockhaus Group 3
4. Why Arquillian?
Testing of complex. multi-layered Java EE applications still is pretty difficult as in many cases the
services offered by the container needs to be in place. Just think of CDI, various annotations,
datasources and so on. One might say, that mocking might replace these concerns and partially this is
correct but still there is a gap between what is provided and what is expected. Arquillian tries to close
this gap by:
● maintaining the life-cycle of of a container (and despite the fact Arquillian is a JBoss project
there are more containers supported than just JBoss )1
● combining all resources to a deployable artifact and providing some facilities to deploy these
Several plugins are available:
● Drone (includes Selenium to test the UI as well)
● Persistence (to create test data out of various formats like XML and JSON)
● Jacoco (to get some metrics about code coverage)
The first test
At first sight an arquillian test doesn’t differ much from a regular unit test:
@RunWith(Arquillian.class)
publicclassCalculatorArquillianTest{
//mustbe@EJB,can'tbe@Inject!Ifyoudon'tbelieve,youcantry...
@EJB
privateCalculatorcalc;
//theoneyouneedunderanycircumstance
@Deployment
publicstaticArchive<?>createTestArchive(){
//checkthehelperfordetailsofhowtogetthethingspackaged
Archive<?>archive=ArchiveHelper.getArchive();
returnarchive;
}
@Test
publicvoidtestAddNumbers(){
floatresult=calc.add(1,2);
Assert.assertEquals(3,result,0);
}
}
The only remarkable things are the @RunWith(Arquillian.class)and the @Deploymentannotations.
Regarding the @RunWithannotation we should not spent too many words, The @Deploymentannotation
looks much more interesting as it seems as if some groundwork is laid in there.
1
This paper will cover JBoss EAP 6.1.1 only
Copyright and all intellectual property belongs to Brockhaus Group 4
5. Creating the archive
One of the main purposes of the method annotated with @Deploymentis to provide the artifact to be
tested.
//theoneyouneedunderanycircumstance
@Deployment
publicstaticArchive<?>createTestArchive(){
//checkthehelperfordetailsofhowtogetthethingspackaged
Archive<?>archive=ArchiveHelper.getArchive();
returnarchive;
}
We have made use of some kind of helper to create the archive as there are two options which will be
explained in more detail.
Create the archive using ShrinkWrap
Using this handy tool, any JavaEE deployable artifact can be created on the fly.
/**doingitthehardway...guessyouwon'tlikeitasEVERYclassplusrelatedstuffneedstobe
specified*/
privatestaticArchive<?>getArchiveManually(){
//creatingarchivemanually
JavaArchiveartifact=
ShrinkWrap.create(JavaArchive.class,ARCHIVE_NAME)
.addPackage(Calculator.class.getPackage())
.addPackage(CalculatorService.class.getPackage())
.addPackage(FooServiceBean.class.getPackage())
.addPackage(Foo.class.getPackage())
.addPackage(FooService.class.getPackage())
.addAsResource("META-INF/persistence.xml")
.addAsResource("META-INF/beans.xml");
//sowemightwriteitforfurtherinspection
if(WRITE_ARCHIVE){
artifact.as(ZipExporter.class)
.exportTo(newFile("D:/Projekte/ffz/tmp/"+ARCHIVE_NAME),
true);
}
returnartifact;
}
As you can see easily, every class, deployment descriptor and so on is added on the fly. For your
convenience the code to write the created archive to the file system is included. This was proven
helpful just to check, whether everything is included properly.
IMHO the only disadvantage might be the vast amount of classes in an average project so we were
pretty confident there must be another way of getting the archive.
Create the archive using maven
One of the de-facto standards in build tools is maven, so why not making use of the famous mvnclean
Copyright and all intellectual property belongs to Brockhaus Group 5
6. packageto get the things done? The following snippet describes how to get the archive loaded into
arquillian.
/**mavendiditforus..wejusthavetoreadthefile*/
privatestaticArchive<?>getArchiveFromFile(){
JavaArchiveartifact=ShrinkWrap
.create(ZipImporter.class,ARCHIVE_NAME)
.importFrom(ARCHIVE_FILE)
.as(JavaArchive.class);
returnartifact;
}
Configuring Arquillian
The initial thing we should tell Arquillian is where to find JBoss,
therefore a small xml file named arquillian.xmlneeds to put aside of
your application.
<?xmlversion="1.0"?>
<arquillianxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<defaultProtocoltype="Servlet3.0"/>
<!--
foradditionalinfosee:
https://docs.jboss.org/author/display/ARQ/Container+configuration
-->
<containerqualifier="jboss"default="true">
<configuration>
<!--thispointstoanexistinginstallation,takecarefor
everythingtobesetupproperly,esp.thedatasources-->
<property
name="jbossHome">D:abcxyzjboss-eap-6.1</property>
</configuration>
</container>
</arquillian>
Be aware of JBoss configured according to your needs, no topic or queue, no data source means no
topic or queue or data source available at testing time. The runtime selection is explained in more
detail here.
Copyright and all intellectual property belongs to Brockhaus Group 6
7. As we suppose you’re making use of maven, here are the dependencies you will need to make the test
run:
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>3.0.2.Final</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<version>1.1.2.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<version>1.1.2.Final</version>
<scope>test</scope>
</dependency>
<!--ifnotusinganyprofile-->
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-managed</artifactId>
<version>7.2.0.Final</version>
</dependency>
Yu might want to check the poms included in the zip files ...
Copyright and all intellectual property belongs to Brockhaus Group 7
8. Now you are almost ready to run your first Arquillian test (mvncleantest/ or using eclipse).
Configuring the runtime modes of arquillian
In the very beginning we should have made the decision of how to use Arquillian as several modes are
supported:
● Remote container Will run in a separate VM, probably on a remote machine.
● Managed container Arquillian starts and stops the container (which must be
installed locally).
● Embedded container Will run in the same VM, Arquillian will manager the container.
Using JBoss, all modes need a JBoss to be installed and localized by arquillian.xml.
We suggest the following approach:
Make use of maven to build your archives and include the necessary dependencies within the POM.
Whatever mode you might choose, put the relevant configuration into a decent profile. We have tested
the managed and embedded option only.
Managed container config
… within <profiles> </profiles> tags obviously:
<profile>
<id>arqillian-jbossas-managed</id>
<dependencies>
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-managed</artifactId>
<version>7.2.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
Copyright and all intellectual property belongs to Brockhaus Group 8
10. If you want to make an embedded test run from eclipse you have to add a system property or
configure properly within the POM:
Copyright and all intellectual property belongs to Brockhaus Group 10
11. Copyright and all intellectual property belongs to Brockhaus Group 11
12. Including persistency(extension)
The full monty of integration testing is provided using persistency. In the field of testing, persistency
first of all means generating test data for later use or testing the creation of data (which is almost
synonymous).
There are several options to get this task done, namely:
● create test data manually using SQL scripts and a pre-filled database.
● create/delete test data manually within the @Before annotated method
● create/delete test data by SQL script
● create/delete test data by means of XML / JSON
Creating test data manually using a pre-filled database
An easy task, just make use of the following:
INSERTINTOFOO(ID,CREATIONTIME,DESCRIPTION)VALUES(998,'2014-02-1812:37:06.73','FooBarOne');
INSERTINTOFOO(ID,CREATIONTIME,DESCRIPTION)VALUES(999,'2014-02-1812:37:06.73','FooBarTwo');
Creating test data manually
The most obvious way of creating (and deleting) test data during a test is doing so within the setUp()
and tearDown() methods of a test :2
@RunWith(Arquillian.class)
publicclassFooServiceArquillianTest{
@EJB
privateFooServicefooService;
privateFoofoo=newFoo();
@Deployment
publicstaticArchive<?>createTestArchive(){
Archive<?>archive=ArchiveHelper.getArchive();
returnarchive;
}
@Before
publicvoidsetUp(){
foo.setCreationTime(newDate(System.currentTimeMillis()));
foo.setDescription("FooBar");
foo.setCreationTime(newDate(System.currentTimeMillis()));
foo=fooService.createFoo(foo);
}
@Test
publicvoidtestFindAll(){
List<Foo>hits=fooService.findAllFoos();
Assert.assertTrue(hits.size()>0);
}
2
more precisely: the methods annotated by @BeforeXxx and @AfterXxx
Copyright and all intellectual property belongs to Brockhaus Group 12
13. @Test
publicvoidtestFindFoosEarlierThan(){
Datefuture=newDate(System.currentTimeMillis()+100000);
List<Foo>hits=fooService.findFoosEarlierThan(future);
Assert.assertTrue(hits.size()>0);
}
@After
publicvoidtearDown(){
List<Foo>hits=fooService.findAllFoos();
for(Foofoo:hits){
fooService.deleteFoo(foo);
}
}
}
Obviously this approach only works well for not-so-complicated objects and associations.
Creating test data by SQL script
Maybe your individual preferences are with SQL and so you want to get the things done by a
customized SQL script. Arquillian supports in doing so by annotations like @ApplyScriptBeforeand
@CreateSchema. We will focus on the first one as we have left schema creation to JPA/Hibernate.
WARNING:
At the time of writing this paper, we have the Alpha6 release of the
framework mentioned, there are several changes even in the names of
the annotations which might drive you crazy. Even the Arquillian book
available is not up to date.
Don’t forget to include the extensions into your POM:
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-persistence-api</artifactId>
<version>1.0.0.Alpha6</version>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-persistence-impl</artifactId>
<version>1.0.0.Alpha6</version>
</dependency>
Presume we have the following script:
INSERTINTOFOO(ID,CREATIONTIME,DESCRIPTION)VALUES(998,'2014-02-1812:37:06.73',
'FooBarOne');
INSERTINTOFOO(ID,CREATIONTIME,DESCRIPTION)VALUES(999,'2014-02-1812:37:06.73',
'FooBarTwo');
Put the script into the /src/test/resources/scriptsfolder of your maven project and annotate the
class accordingly:
Copyright and all intellectual property belongs to Brockhaus Group 13