JBoss.orgCommunity Documentation
Arquillian's forte is not only in its ease of use, but also in its flexibility. Good integration testing is not just about testing in any container, but rather testing in the container you are targeting. It's all too easy to kid ourselves by validating components in a specialized testing container, only to realize that the small variations causes the components fail when it comes time to deploy to the application for real. To make tests count, you want to execute them in the real container.
Arquillian supports a variety of target containers out of the box, which will be covered in this chapter. If the container you are using isn't supported, Arquillian makes it very easy to plug in your own implementation.
You can run the same test case against various containers with Arquillian. The test class does not reference the container directly, which means you don't get locked into a proprietary test environment. It also means you can select the optimal container for development or easily test the compatibility of your application.
Arquillian recognizes three container interaction styles:
a remote container resides in a separate JVM from the test runner; Arquillian binds to the container to deploy and undeploy the test archive and invokes tests via a remote protocol (typically HTTP)
an embedded container resides in the same JVM as the test runner; lifecycle managed by Arquillian; tests are executed via a local protocol for containers without a web component (e.g., Embedded EJB) and via a remote protocol for containers that have a web component (e.g., Embedded Java EE)
a managed container is the same as a remote container, but in addition, its lifecycle (startup/shutdown) is managed by Arquillian and is run as a separate process
Containers can be further classified by their capabilities. There are three common catagories:
A fully compliant Java EE application server (e.g., GlassFish, JBoss AS, Embedded GlassFish)
A Servlet container (e.g., Jetty, Tomcat)
A standalone bean container (e.g., Weld SE, Spring)
Arquillian provides SPIs that handle each of the tasks involved in controlling the runtime environment, executing the tests and aggregating the results. So in theory, you can support just about any environment that can be controlled with the set of hooks you are given.
While the management of an embedded container is straightforward, you may wonder how Arquillian knows where the remote and managed containers are installed. Actually, Arquillian only needs to know the install path of managed containers (e.g., jbossas-managed-6). In this case, since Arquillian manages the container process, it must have access to the container's startup script. For managed JBoss AS containers, the install path is read from the environment variable JBOSS_HOME.
For remote containers (e.g., jbossas-remote-6), Arquillian simply needs to know that the container is running and communicates with it using a remote protocol (e.g., JNDI). For remote JBoss AS containers, the JNDI settings are set in a jndi.properties file on the classpath. You also have to set the remote address and HTTP port in the container configuration if they differ from the default values (localhost and 8080 for JBoss AS, respectively).
The implementations provided so far are shown in the table below. Also listed is the artifactId of the JAR that provides the implementation. To execute your tests against a container, you must include the artifactId that corresponds to that container on the classpath. Use the following Maven profile definition as a template to add support for a container to your Maven build, replacing %artifactId% with the artifactId from the table. You then activate the profile when executing the tests just as you did in the Chapter 3, Getting started chapter.
<profile>
<id>%artifactId%</id>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>%artifactId%</artifactId>
<version>${arquillian.version}</version>
</dependency>
</dependencies>
</profile>
Table 4.1. Target containers supported by Arquillian
Container name | Container type | Spec compliance | artifactId |
---|---|---|---|
JBoss AS 5 | remote | Java EE 5 | arquillian-jbossas-remote-5 |
JBoss AS 5.1 | remote | Java EE 5 | arquillian-jbossas-remote-5.1 |
JBoss AS 5.1 | managed | Java EE 5 | arquillian-jbossas-managed-5.1 |
JBoss AS 6.0 M4 | remote | Java EE 6 | arquillian-jbossas-remote-6 |
JBoss AS 6.0 M4 | managed | Java EE 6 | arquillian-jbossas-managed-6 |
JBoss AS 6.0 M4 | embedded | Java EE 6 | arquillian-jbossas-embedded-6 |
JBoss Reloaded 1.0 | embedded | JBoss MC | arquillian-reloaded-embedded-1 |
GlassFish 3.0 | remote | Java EE 6 | arquillian-glassfish-remote-3 |
GlassFish 3.0 | embedded | Java EE 6 | arquillian-glassfish-embedded-3 |
Tomcat 6.0 | embedded | Servlet 2.5 | arquillian-tomcat-embedded-6 |
Jetty 6.1 | embedded | Servlet 2.5 | arquillian-jetty-embedded-6.1 |
Jetty 7.0 | embedded | Servlet ~3.0 | arquillian-jetty-embedded-7 |
Weld SE 1.0 | embedded | CDI | arquillian-weld-se-embedded-1 |
Weld EE 1.1 | embedded | CDI | arquillian-weld-ee-embedded-1.1 |
IronJacamar 1.0 | embedded | JCA 1.6 | org.jboss.ironjacamar:ironjacamar-embedded-arquillian |
Apache OpenWebBeans 1.0 | embedded | CDI | arquillian-openwebbeans-embedded-1 |
Apache OpenEJB 3.1 | embedded | EJB 3.0 | arquillian-openejb-embedded-3.1 |
Support for other containers is planned, including Weblogic (remote), WebSphere (remote) and Hibernate.
You can come a long way with default values, but at some point you may need to customize some of the container
settings to fit your environment. We're going to have a look at how this can be done with Arquillian.
Arquillian will look for a file named arquillian.xml
in the root of your classpath.
If it exists it will be auto loaded, else default values will be used. So this file is not a requirement.
Lets imagine that we're working for the company example.com
and in our environment we have two servers;
test.example.com
and hudson.example.com
. test.example.com
is the JBoss instance we use for our integration tests and hudson.example.com
is our continuous integration server
that we want to run our integration suite from. By default, Arquillian will use localhost, so we need to tell it to use
test.example.com
to run the tests.
<?xml version="1.0"?>
<arquillian xmlns="http://jboss.com/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jboss="urn:arq:org.jboss.arquillian.container.jbossas.remote_6">
<engine>
<deploymentExportPath>/tmp</deploymentExportPath>
</engine>
<jboss:container>
<jboss:remoteServerAddress>test.example.com</jboss:remoteServerAddress>
<jboss:remoteServerHttpPort>8181</jboss:remoteServerHttpPort>
<jboss:localDeploymentBindAddress>
hudson.example.com
</jboss:localDeploymentBindAddress>
<jboss:localDeploymentBindPort>7000</jboss:localDeploymentBindPort>
</jboss:container>
</arquillian>
That should do it! "Each type of container has it's own XML namespace for configuration - here we use the JBoss AS 6.0
Remote container. Each container has different configuration options. Next step is to create a
container
element in that namespace and add the options you want to configure inside.
In this example we're saying that the server we want to test against can be found on
address test.example.com
using port 8181, and the remote server can communicate back to us
on address hudson.example.com
on port 7000. Some containers expect to be given a URL from which
they can retrieve the application to be deployed. For these containers, Arquillian will start a local HTTP server.