JBoss.orgCommunity Documentation

Arquillian: An integration testing framework for Containers

Reference Guide


Preface: Test in the container!
1. Introduction
1.1. Mission statement
1.2. Architecture overview
1.3. Integration testing in Java EE
1.3.1. Testing the real component
1.3.2. Finding a happy medium
1.3.3. Controlling the test classpath
1.4. Usage scenarios
2. Introductory examples
2.1. Testing an EJB
2.2. Testing CDI beans
2.3. Testing JPA
2.4. Testing JMS
3. Getting started
3.1. Setting up Arquillian in a Maven project
3.2. Writing your first Arquillian test
3.3. Setting up and running the test in Maven
3.4. Setting up and running the test in Eclipse
3.5. Setting up and running the test in NetBeans
4. Target containers
4.1. Container varieties
4.2. Container management
4.3. Supported containers
4.4. Container configuration
5. Test enrichment
5.1. Injection into the test case
5.2. Active scopes
6. Test execution
6.1. Anatomy of a test
6.2. ShrinkWrap packaging
6.3. Test archive deployment
6.4. Enriching the test class
6.5. Negotiating test execution
6.6. Test run modes
6.6.1. Mode: in-container
6.6.2. Mode: as-client
6.6.3. Mode: mixed
7. Debugging remote tests
7.1. Debugging in Eclipse
7.1.1. Attaching the IDE debugger to the container
7.1.2. Launching the test in debug mode
7.1.3. Stepping into external libraries
7.2. Assertions in remote tests
7.2.1. Enabling assertions in JBoss AS
8. Build system integration
8.1. Arquillian's active build ingredient
8.2. Integrating Arquillian into a Gradle build
8.2.1. apply from: common
8.2.2. Strategy #1: Container-specific test tasks
8.2.3. Strategy #2: Test profiles
8.3. Integrating Arquillian into an Ant (+Ivy) build
9. Advanced use cases
9.1. Descriptor deployment
9.2. Resource injection
9.3. Multiple Deployments
9.4. Multiple Containers
9.5. Protocol selection
10. Extending Arquillian
11. Complete Extension/Framework Reference
11.1. Performance
11.2. JSFUnit
11.3. Drone
12. Complete Container Reference
12.1. JBoss AS 5 - Remote
12.1.1. Configuration
12.2. JBoss AS 5.1 - Remote
12.2.1. Configuration
12.3. JBoss AS 5.1 - Managed
12.3.1. Configuration
12.4. JBoss AS 6.0 - Remote
12.4.1. Configuration
12.5. JBoss AS 6.0 - Managed
12.5.1. Configuration
12.6. JBoss AS 6.0 - Embedded
12.6.1. Configuration
12.7. JBoss Reloaded 1.0 - Embedded
12.7.1. Configuration
12.8. GlassFish 3.1 - Embedded
12.8.1. Configuration
12.9. GlassFish 3.1 - Remote
12.9.1. Configuration
12.10. Tomcat 6.0 - Embedded
12.10.1. Configuration
12.11. Jetty 6.1 - Embedded
12.11.1. Configuration
12.12. Jetty 7.0 - Embedded
12.12.1. Configuration
12.13. Weld SE 1.0 - Embedded
12.13.1. Configuration
12.14. Weld SE 1.1 - Embedded
12.14.1. Configuration
12.15. Weld EE 1.1 - Embedded
12.15.1. Configuration
12.16. Apache OpenWebBeans 1.0 - Embedded
12.16.1. Configuration
12.17. Apache OpenEJB 3.1 - Embedded
12.17.1. Configuration
13. Complete Protocol Reference
13.1. Local
13.1.1. Configuration
13.2. Servlet 2.5
13.2.1. Configuration
13.3. Servlet 3.0
13.3.1. Configuration

Ever since the inception of Java EE, testing enterprise applications has been a major pain point. Testing business components, in particular, can be very challenging. Often, a vanilla unit test isn't sufficient for validating such a component's behavior. Why is that? The reason is that components in an enterprise application rarely perform operations which are strictly self-contained. Instead, they interact with or provide services for the greater system. They also have declarative functionality which gets applied at runtime. You could say "no business component is an island."

The way the component interacts with the system is just as important as the work it performs. Even with the application separated into more layers than your favorite Mexican dip, to validate the correctness of a component, you have to observe it carrying out its work—in situ. Unit tests and mock testing can only take you so far. Business logic aside, how do you test your component's "enterprise" semantics?

Especially true of business components, you eventually have to ensure that the declarative services, such as dependency injection and transaction control, actually get applied and work as expected. It means interacting with databases or remote systems and ensuring that the component plays well with its collaborators. What happens when your Message Driven Bean can't parse the XML message? Will the right component be injected? You may just need to write a test to explore how the declarative services behave, or that your application is configured correctly to use them. This style of testing needed here is referred to as integration testing, and it's an essential part of the enterprise development process.

Arquillian, a new testing framework developed at JBoss.org, empowers the developer to write integration tests for business objects that are executed inside a container or that interact with the container as a client. The container may be an embedded or remote Servlet container, Java EE application server, Java SE CDI environment or any other container implementation provided. Arquillian strives to make integration testing no more complicated than basic unit testing.

The importance of Arquillian in the Java EE space cannot be emphasized enough. If writing good tests for Java EE projects is some dark art in which knowledge is shared only by the Java gurus, people are either going to be turned off of Java EE or a lot of fragile applications are going to be written. Arquillian is set to become the first comprehensive solution for testing Java EE applications, namely because it leverages the container rather than a contrived runtime environment.

This guide documents Arquillian's architecture, how to get started using it and how to extend it. If you have questions, please use the discussion forum in the top-level Arquillian space on JBoss.org. We also provide a JIRA issue tracking system for bug reports and feature requests. If you are interested in the development of Arquillian, or want to translate this documentation into your language, we welcome you to join us in the Arquillian Development subspace on JBoss.org.

We believe that integration testing should be no more complex than writing a basic unit test. We created Arquillian to realize that goal. One of the major complaints we've heard about Seam 2 testing (i.e., SeamTest) was, not that it isn't possible, but that it isn't flexible and it's difficult to setup. We wanted to correct those shortcomings with Arquillian.

Testing needs vary greatly, which is why it's so vital that, with Arquillian (and ShrinkWrap), we have decomposed the problem into its essential elements. The result is a completely flexible and portable integration testing framework.

Arquillian is the missing link in Java EE development. Developers have long had to fend for themselves in the testing stage, burdened with bootstrapping the infrastructure on which the test depends. That's time lost, and it places a high barrier to entry on integration testing. Arquillian tears down that barrier.

Arquillian is a container-oriented test framework. It picks up where unit tests leave off, targeting the integration of application code inside a real runtime environment. Just as Java EE 5 simplified the server programming model by providing declarative services for POJOs, Arquillian equips tests with container lifecycle management and enrichment.

With Arquillian, you write a basic test case and annotate it with declarative behavior that says, "run with Arquillian." Launching the test is as simple as right-clicking the test class in the IDE and selecting Run As > JUnit or TestNG test. Based on the classpath configuration, Arquillian starts or binds to the target container (JBoss AS, GlassFish, OpenEJB, etc) and deploys the test case bundled with the test archive defined in the @Deployment method. Your test executes inside the container and enjoys all the same services as an application component. That means you get dependency and resource injection into the test, you can access EJBs, you can load a persistence unit, you can get a handle to a database connection, etc. Yet, on the surface, it looks like any other unit test. (Arquillian also has a client execution mode, which only deploys the test archive, not the test case).

Instead of bringing your runtime to the test, Arquillian brings your test to the runtime.

Features of Arquillian include:

No longer does writing a test involve system administration tasks. No more custom scripts or copy-paste Maven configuration. No more full builds. No more test classpath mayhem. No more looking up resources manually in JNDI. No more reliance on coarse-grained, black-box testing.

Arquillian keeps you focused on the test, while enjoying the services provided by the container. And it's turning heads.

Arquillian combines a unit testing framework (JUnit or TestNG), ShrinkWrap, and one or more supported target containers (Java EE container, servlet container, Java SE CDI environment, etc) to provide a simple, flexible and pluggable integration testing environment.

At the core, Arquillian provides a custom test runner for JUnit and TestNG that turns control of the test execution lifecycle from the unit testing framework to Arquillian. From there, Arquillian can delegate to service providers to setup the environment to execute the tests inside or against the container. An Arquillian test case looks just like a regular JUnit or TestNG test case with two declarative enhancements, which will be covered later.

Since Arquillian works by replacing the test runner, Arquillian tests can be executed using existing test IDE, Ant and Maven test plugins without any special configuration. Test results are reported just like you would expect. That's what we mean when we say using Arquillian is no more complicated than basic unit testing.

At this point, it's appropriate to pause and define the three aspects of an Arquillian test case. This terminology will help you better understand the explainations of how Arquillian works.

The test case is dispatched to the container's environment through coordination with ShrinkWrap, which is used to declaratively define a custom Java EE archive that encapsulates the test class and its dependent resources. Arquillian packages the ShrinkWrap-defined archive at runtime and deploys it to the target container. It then negotiates the execution of the test methods and captures the test results using remote communication with the server. Finally, Arquillian undeploys the test archive. We'll go into more detail about how Arquillian works in a later chapter.

So what is the target container? Some proprietary testing container that emulates the behavior of the technology (Java EE)? Nope, it's pluggable. It can be your actual target runtime, such as JBoss AS, GlassFish or Tomcat. It can even been an embedded container such as JBoss Embedded AS, GlassFish Embedded or Weld SE. All of this is made possible by a RPC-style (or local, if applicable) communication between the test runner and the environment, negotiating which tests are run, the execution, and communicating back the results. This means two things for the developer:

With that in mind, let's consider where we are today with integration testing in Java EE and why an easy solution is needed.

Integration testing is very important in Java EE. The reason is two-fold:

The first reason is inherent in enterprise applications. For the application to perform any sort of meaningful work, it has to pull the strings on other components, resources (e.g., a database) or systems (e.g., a web service). Having to write any sort of test that requires an enterprise resource (database connection, entity manager, transaction, injection, etc) is a non-starter because the developer has no idea what to even use. Clearly there is a need for a simple solution, and Arquillian fills that void.

Some might argue that, as of Java EE 5, the business logic performed by most Java EE components can now be tested outside of the container because they are POJOs. But let's not forget that in order to isolate the business logic in Java EE components from infrastructure services (transactions, security, etc), many of those services were pushed into declarative programming constructs. At some point you want to make sure that the infrastructure services are applied correctly and that the business logic functions properly within that context, justifying the second reason that integration testing is important in Java EE.

Let's move on and consider some typical usage scenarios for Arquillian.

With the strategy defined above, where the test case is executed in the container, you should get the sense of the freedom you have to test a broad range of situations that may have seemed unattainable when you only had the primitive unit testing environment. In fact, anything you can do in an application you can now do in your test class.

A fairly common scenario is testing an EJB session bean. As you are inside the container, you can simply do a JNDI lookup to get the EJB reference and your test becomes a client of the EJB. But having to use JNDI to get a reference to the EJB is inconvenient (at least to Java EE 5 developers that have become accustomed to annotation-based dependency injection). Arquillian allows you to use the @EJB annotation to inject the reference to an EJB session bean into your test class.

EJB session beans are one type of Java EE resource you may want to access. But that's just the beginning. You can access any resource available in a Java EE container, from a UserTransaction to a DataSource to a mail session. Any of these resources can be injected directly into your test class using the Java EE 5 @Resource annotation.

Resource injections are convenient, but they are so Java EE 5. In Java EE 6, when you think dependency injection, you think JSR-299: CDI. Your test class can access any bean in the ShrinkWrap-defined archive, provided the archive contains a beans.xml file to make it a bean archive. And you can inject bean instances directly into your class using the @Inject annotation, or you can inject an Instance reference to the bean, allowing you to create a bean instance when needed in the test. Of course, you can do anything else you can do with CDI within your test as well.

Another important scenario in integration testing is performing data access. If the ShrinkWrap-defined archive contains a persistence.xml descriptor, the persistence unit will be started when the archive is deployed and you can perform persistence operations. You can obtain a reference to an EntityManager by injecting it into your class with @PersistenceContext or from a CDI producer-field. Alternatively, you can execute the persistence operation indirectly through an EJB session bean or a managed bean.

Those examples should give you an idea of some of the tasks that are possible from within an Arquillian-enhanced test case. Now that you have plenty of motivation for using Arquillian, let's look at how to get started using Arquillian.

The following examples demonstrate the use of Arquillian. Currently Arquillian is distributed as a Maven only project, so you'll need to grab the examples from Git. You can choose between a JUnit example and a TestNG example. In this tutorial we show you how to use both.

git clone git://github.com/arquillian/arquillian.git arquillian
cd arquillian
git checkout 1.0.0-SNAPSHOT
If you want to try the JUnit examples do:
cd examples/junit
Or if you want to try the TestNG examples do:
cd examples/testng

Running these tests from the command line is easy. The examples run against all the servers supported by Arquillian (of course, you must choose a container that is capable of deploying EJBs for these tests). To run the test, we'll use Maven. For this tutorial, we'll use JBoss AS 6 (currently at Milestone 3), for which we use the jbossas-remote-6 profile.

First, make sure you have a copy of JBoss AS; you can download it from jboss.org. We strongly recommend you use a clean copy of JBoss AS. Unzip JBoss AS to a directory of your choice and start it; we'll use $JBOSS_HOME to refer to this location throughout the tutorial.

$ unzip jboss-6.0.0.Final.zip && mv jboss-6.0.0.Final $JBOSS_HOME && $JBOSS_HOME/bin/run.sh

Now, we tell Maven to run the tests, for both JUnit and TestNG:

$ mvn test -Pjbossas-remote-6

$ cd ../arquillian-example-junit/
$ mvn test -Pjbossas-remote-6

You can also run the tests in an IDE. We'll show you how to run the tests in Eclipse, with m2eclipse installed, next.

Before running an Arquillian test in Eclipse, you must have the plugin for the unit testing framework you are using installed. Eclipse ships with the JUnit plugin, so you are already setup if you selected JUnit. If you are writing your tests with TestNG, you need the Eclipse TestNG plugin.

Since the examples in this guide are based on a Maven 2 project, you will also need the m2eclipse plugin. Instructions for using the m2eclipse update site to add the m2eclipse plugin to Eclipse are provided on the m2eclipse home page. For more, read the m2eclipse reference guide.

Once the plugins are installed, import your Maven project into the Eclipse workspace. Before executing the test, you need to enable the profile for the target container, as we did on the command line. We'll go ahead and activate the profile globally for the project (we also need the default profile, read the note above for more). Right click on the project and select Properties. Select the Maven property sheet and in the first form field, enter jbossas-remote-6; you also need to tell Maven to not resolve dependencies from the workspace (this interferes with resource loading):

Maven settings for project

Click OK and accept the project changes. Before we execute tests, make sure that Eclipse has properly processed all the resource files by running a full build on the project by selecting Clean from Project menu. Now you are ready to execute tests.

Assuming you have JBoss AS started from running the tests on the command line, you can now execute the tests. Right click on the InjectionTestCase.java file in the Package Explorer and select Run As... > JUnit Test or Run As... > TestNG Test depending on which unit testing framework the test is using.

Running the test from Eclipse using TestNG

You can now execute all the tests from Eclipse!

Here's an example of an JUnit Arquillian test that validates the GreetingManager EJB session bean again, but this time it's injected into the test class using the @Inject annotation. You could also make GreenManager a basic managed bean and inject it with the same annotation. The test also verifies that the CDI BeanManager instance is available and gets injected. Notice that to inject beans with CDI, you have to add a beans.xml file to the test archive.

import javax.enterprise.inject.spi.BeanManager;

import javax.inject.Inject;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.acme.ejb.GreetingManager;
import com.acme.ejb.GreetingManagerBean;
@RunWith(Arquillian.class)
public class InjectionTestCase
{
   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(GreetingManager.class, GreetingManagerBean.class)
         .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
   }
   @Inject GreetingManager greetingManager;
   @Inject BeanManager beanManager;
   @Test
   public void shouldBeAbleToInjectCDI() throws Exception {
      String userName = "Earthlings";
      Assert.assertNotNull("Should have the injected the CDI bean manager", beanManager);
      Assert.assertEquals("Hello " + userName, greetingManager.greet(userName));
   }
}

In order to test JPA, you need both a database and a persistence unit. For the sake of example, let's assume we are going to use the default datasource provided by the container and that the tables will be created automatically when the persistence unit starts up. Here's a persistence unit configuration that satisfies that scenario.


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
   xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/persistence
      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
   <persistence-unit name="users" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
      </properties>
   </persistence-unit>
</persistence>

Now let's assume that we have an EJB session bean that injects a persistence context and is responsible for storing and retrieving instances of our domain class, User. We've catered it a bit to the test for purpose of demonstration.

public @Stateless class UserRepositoryBean implements UserRepository {

   @PersistenceContext EntityManager em;
   public void storeAndFlush(User u) {
      em.persist(u);
      em.flush();
   }
   public List<User> findByLastName(String lastName) {
      return em.createQuery("select u from User u where u.lastName = :lastName")
         .setParameter("lastName", lastName)
         .getResultList();
   }
}

Now let's create an Arquillian test to ensure we can persist and subsequently retrieve a user. Notice that we'll need to add the persistence unit descriptor to the test archive so that the persistence unit is booted in the test archive.

public class UserRepositoryTest extends Arquillian {

   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(User.class, UserRepository.class, UserRepositoryBean.class)
         .addAsManifestResource(
            "test-persistence.xml", 
            ArchivePaths.create("persistence.xml"));
   }
   private static final String FIRST_NAME = "Agent";
   private static final String LAST_NAME = "Kay";
   @EJB
   private UserRepository userRepository;
   @Test
   public void testCanPersistUserObject() {
      User u = new User(FIRST_NAME, LAST_NAME);
      userRepository.storeAndFlush(u);
      
      List<User> users = userRepository.findByLastName(LAST_NAME);
      Assert.assertNotNull(users);
      Assert.assertTrue(users.size() == 1);
      Assert.assertEquals(users.get(0).getLastName(), LAST_NAME);
      Assert.assertEquals(users.get(0).getFirstName(), FIRST_NAME); 
   }
}
      

Here's another JUnit Arquillian test that exercises with JMS, something that may have previously seemed very tricky to test. The test uses a utility class QueueRequestor to encapsulate the low-level code for sending and receiving a message using a queue.

import javax.annotation.Resource;

import javax.jms.*;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.acme.ejb.MessageEcho;
import com.acme.util.jms.QueueRequestor;
@RunWith(Arquillian.class)
public class InjectionTestCase {
   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(MessageEcho.class, QueueRequestor.class);
   }
   @Resource(mappedName = "/queue/DLQ")
   private Queue dlq;
   @Resource(mappedName = "/ConnectionFactory")
   private ConnectionFactory factory;
   @Test
   public void shouldBeAbleToSendMessage() throws Exception {
      String messageBody = "ping";
      Connection connection = factory.createConnection();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      QueueRequestor requestor = new QueueRequestor((QueueSession) session, dlq);
      connection.start();
      Message request = session.createTextMessage(messageBody);
      Message response = requestor.request(request, 5000);
      Assert.assertEquals("Should have responded with same message", messageBody, ((TextMessage) response).getText());
   }
}

That should give you a taste of what Arquillian tests look like. To learn how to setup Arquillian in your application and start developing tests with it, refer to the Chapter 3, Getting started chapter.

We've promised you that integration testing with Arquillian is no more complicated than writing a unit test. Now it's time to prove it to you. In this chapter, we'll look at what is required to setup Arquillian in your project, how to write an Arquillian test case, how to execute the test case and how the test results are displayed. That sounds like a lot, but you'll be writing your own Arquillian tests in no time. (You'll also learn about Chapter 7, Debugging remote tests in Chapter 7).

The quickest way to get started with Arquillian is to add it to an existing Maven 2 project. Regardless of whether you plan to use Maven as your project build, we recommend that you take your first steps with Arquillian this way so as to get to your first green bar with the least amount of distraction.

The first thing you should do is define a Maven property for the version of Arquillian you are going to use. This way, you only have to maintain the version in one place and can reference it using the Maven variable syntax everywhere else in your build file.


<properties>
   <arquillian.version>1.0.0-SNAPSHOT</arquillian.version>
</properties>

Make sure you have the correct APIs available for your test. In this test we are going to use CDI:


<dependency> 
   <groupId>javax.enterprise</groupId> 
   <artifactId>cdi-api</artifactId> 
   <version>1.0-SP1</version>  
</dependency>

Next, you'll need to decide whether you are going to write tests in JUnit 4.x or TestNG 5.x. Once you make that decision (use TestNG if you're not sure), you'll need to add either the JUnit or TestNG library to your test build path as well as the corresponding Arquillian library.

If you plan to use JUnit 4, begin by adding the following two test-scoped dependencies to the <dependencies> section of your pom.xml.


<dependency> 
   <groupId>junit</groupId> 
   <artifactId>junit</artifactId> 
   <version>4.8.1</version> 
   <scope>test</scope> 
</dependency> 

<dependency>
   <groupId>org.jboss.arquillian</groupId>
   <artifactId>arquillian-junit</artifactId>
   <version>${arquillian.version}</version>
   <scope>test</scope>
</dependency>

If you plan to use TestNG, then add these two test-scoped dependencies instead:


<dependency> 
   <groupId>org.testng</groupId> 
   <artifactId>testng</artifactId> 
   <version>5.12.1</version> 
   <scope>test</scope> 
</dependency> 

<dependency>
   <groupId>org.jboss.arquillian</groupId>
   <artifactId>arquillian-testng</artifactId>
   <version>${arquillian.version}</version>
   <scope>test</scope>
</dependency>

That covers the libraries you need to write your first Arquillian test case. We'll revisit the pom.xml file in a moment to add the library you need to execute the test.

You're now going to write your first Arquillian test. But in order to write a test, we need to have something to test. So let's first create a managed bean that we can invoke.

We'll help out those Americans still trying to convert to the metric system by providing them a Fahrenheit to Celsius converter.

Here's our TemperatureConverter:

public class TemperatureConverter {


   public double convertToCelsius(double f) {
      return ((- 32) * 5 / 9);
   }
   public double convertToFarenheit(double c) {
      return ((* 9 / 5) + 32);
   }
}

Now we need to validate that this code runs. We'll be creating a test in the src/test/java classpath of the project.

Granted, in this trivial case, we could simply instantiate the implementation class in a unit test to test the calculations. However, let's assume that this bean is more complex, needing to access enterprise services. We want to test it as a full-blown container-managed bean, not just as a simple class instance. Therefore, we'll inject the bean into the test class using the @Inject annotation.

You're probably very familiar with writing tests using either JUnit or TestNG. A regular JUnit or TestNG test class requires two enhancements to make it an Arquillian integration test:

The deployment archive for the test is defined using a static method annotated with Arquillian's @Deployment annotation that has the following signature:

public static Archive<?> methodName();

We'll add the managed bean to the archive so that we have something to test. We'll also add an empty beans.xml file, so that the deployment is CDI-enabled:

@Deployment

public static JavaArchive createTestArchive() {
   return ShrinkWrap.create(JavaArchive.class, "test.jar")
      .addClasses(TemperatureConverter.class)
      .addAsManifestResource(
            new ByteArrayAsset("<beans/>".getBytes()), 
            ArchivePaths.create("beans.xml"));
}

The JUnit and TestNG versions of our test class will be nearly identical. They will only differ in how they hook into the Arquillian test runner.

When creating the JUnit version of the Arquillian test case, you will define at least one test method annotated with the JUnit @Test annotation and also annotate the class with the @RunWith annotation to indicate that Arquillian should be used as the test runner for this class.

Here's the JUnit version of our test class:

@RunWith(Arquillian.class)

public class TemperatureConverterTest {
   @Inject
   private TemperatureConverter converter;
   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(TemperatureConverter.class)
         .addAsManifestResource(
            EmptyAsset.INSTANCE, 
            ArchivePaths.create("beans.xml")); 
   }
   @Test
   public void testConvertToCelsius() {
      Assert.assertEquals(converter.convertToCelsius(32d), 0d);
      Assert.assertEquals(converter.convertToCelsius(212d), 100d);
   }
   @Test
   public void testConvertToFarenheit() {
      Assert.assertEquals(converter.convertToFarenheit(0d), 32d);
      Assert.assertEquals(converter.convertToFarenheit(100d), 212d);
   }
}

TestNG doesn't provide anything like JUnit's @RunWith annotation, so instead the TestNG version of the Arquillian test case must extend the Arquillian class and define at least one method annotated with TestNG's @Test annotation.

public class TemperatureConverterTest extends Arquillian {

   @Inject
   private TemperatureConverter converter;
   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(TemperatureConverter.class)
         .addAsManifestResource(
            EmptyAsset.INSTANCE,, 
            ArchivePaths.create("beans.xml")); 
   }
   @Test
   public void testConvertToCelsius() {
      Assert.assertEquals(converter.convertToCelsius(32d), 0d);
      Assert.assertEquals(converter.convertToCelsius(212d), 100d);
   }
   @Test
   public void testConvertToFarenheit() {
      Assert.assertEquals(converter.convertToFarenheit(0d), 32d);
      Assert.assertEquals(converter.convertToFarenheit(100d), 212d);
   }
}

As you can see, we are not instantiating the bean implementation class directly, but rather using the CDI reference provided by the container at the injection point, just as it would be used in the application. (If the target container supports EJB, you could replace the @Inject annotation with @EJB). Now let's see if this baby passes!

As we've been emphasizing, this test is going to run inside of a container. That means you have to have a container running somewhere. While you can execute tests in an embedded container or a Java SE CDI environment, we're going to start off by testing using the real deal.

If you haven't already, download the latest version of JBoss AS 6.0 from the JBoss AS download page, extract the distribution and start the container.

Since Arquillian needs to perform JNDI lookups to get references to the components under test, we need to include a jndi.properties file on the test classpath. Create the file src/test/resources/jndi.properties and populate it with the following contents:

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces 
java.naming.provider.url=jnp://localhost:1099

Next, we're going to return to pom.xml to add another dependency. Arquillian picks which container it's going to use to deploy the test archive and negotiate test execution using the service provider mechanism, meaning which implementation of the DeployableContainer SPI is on the classpath. We'll control that through the use of Maven profiles. Add the following profiles to pom.xml:


<profiles>
   <profile>
      <id>jbossas-remote-6</id>
      <dependencies>
         <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-remote-6</artifactId>
            <version>${arquillian.version}</version>
         </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>6.0.0.Final</version>
            <type>pom</type>
        </dependency>
      </dependencies>
   </profile>
</profiles>

You would setup a similar profile for each Arquillian-supported container in which you want your tests executed.

All that's left is to execute the tests. In Maven, that's easy. Simply run the Maven test goal with the jbossas-remote-6 profile activated:

mvn test -Pjbossas-remote-6

You should see that the two tests pass.

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TemperatureConverterTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.964 sec

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

The tests are passing, but we don't see a green bar. To get that visual, we need to run the tests in the IDE. Arquillian tests can be executed using existing IDE plugins for JUnit and TestNG, respectively, or so you've been told. It's once again time to prove it.

Before running an Arquillian test in Eclipse, you must have the plugin for the unit testing framework you are using installed. Eclipse ships with the JUnit plugin, so you are already setup if you selected JUnit. If you are writing your tests with TestNG, you need the Eclipse TestNG plugin.

Note

Since the example in this guide is based on a Maven 2 project, you will also need the m2eclipse plugin. Instructions for using the m2eclipse update site to add the m2eclipse plugin to Eclipse are provided on the m2eclipse home page. For more, read the m2eclipse reference guide.

Once the plugins are installed, import your Maven project into the Eclipse workspace. Before executing the test, you need to enable the profile for the target container, as you did in the previous section. We'll go ahead and activate the profile globally for the project. Right click on the project and select Properties. Select the Maven property sheet and in the first form field, enter jbossas-remote-6; you also need to tell Maven to not resolve depedencies from the workspace (this interferes with resource loading):

Maven settings for project

Click OK and accept the project changes. Before we execute tests, make sure that Eclipse has properly processed all the resource files by running a full build on the project by selecting Clean from Project menu. Now you are ready to execute tests.

Right click on the TemperatureConverterTest.java file in the Package Explorer and select Run As... > JUnit Test or Run As... > TestNG Test depending on which unit testing framework the test is using.

Running the the JUnit test in Eclipse

As you can see, there was no special configuration necessary to execute the tests in either Eclipse or NetBeans.

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:

Containers can be further classified by their capabilities. There are three common catagories:

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.

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>

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. The JBoss AS container by default use the Servlet protocol, so we have to override the default configuration.


<?xml version="1.0"?>
    
<arquillian xmlns="http://jboss.com/arquillian"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

 <container qualifier="jbossas" default="true">
     <configuration>
        <property name="providerUrl">jnp://test.example.com:1099</property>
     </configuration>
     <protocol type="Servlet 3.0">
        <configuration>
            <property name="host">test.example.com</property>
            <property name="port">8181</property>
        </configuration>
     </protocol>
 </container>
</arquillian>

That should do it! Here we use the JBoss AS 6.0 Remote container which default use the Servlet 3.0 protocol implementation. We override the default Servlet configuration to say that the http requests for this container can be executed over test.example.com:8181, but we also need to configure the container so it knows where to deploy our archives. We could for example have configured the Servlet protocol to communicate with a Apache server in front of the JBoss AS Server if we wanted to. Each container has different configuration options.

When you use a unit testing framework like JUnit or TestNG, your test case lives in a world on its own. That makes integration testing pretty difficult because it means the environment in which the business logic executes must be self-contained within the scope of the test case (whether at the suite, class or method level). The bonus of setting up this environment in the test falls on the developer's shoulders.

With Arquillian, you no longer have to worry about setting up the execution environment because that is all handled for you. The test will either be running in a container or a local CDI environment. But you still need some way to hook your test into this environment.

A key part of in-container integration testing is getting access the container-managed components that you plan to test. Using the Java new operator to instantiate the business class is not suitable in this testing scenario because it leaves out the declaratives services that get applied to the component at runtime. We want the real deal. Arquillian uses test enrichment to give us access to the real deal. The visible result of test enrichment is injection of container resources and beans directly into the test class.

Before Arquillian negotiates the execution of the test, it enriches the test class by satisfying injection points specified declaratively using annotations. There are three injection-based enrichers provided by Arquillian out of the box:

The first two enrichers use JNDI to lookup the instance to inject. The CDI injections are handled by treating the test class as a bean capable of receiving standard CDI injections.

The @Resource annotation gives you access to any object which is available via JNDI. It follows the standard rules for @Resource (as defined in the Section 2.3 of the Common Annotations for the Java Platform specification).

The @EJB annotation performs a JNDI lookup for the EJB session bean reference using the following equation in the specified order:

"java:global/test.ear/test/" + fieldType.getSimpleName() + "Bean",
"java:global/test.ear/test/" + fieldType.getSimpleName(),
"java:global/test/" + fieldType.getSimpleName(),
"java:global/test/" + fieldType.getSimpleName() + "Bean",
"java:global/test/" + fieldType.getSimpleName() + "/no-interface",
"test/" + unqualified interface name + "Bean/local",
"test/" + unqualified interface name + "Bean/remote",
"test/" + unqualified interface name + "/no-interface",
unqualified interface name + "Bean/local",
unqualified interface name + "Bean/remote",
unqualified interface name + "/no-interface"

If no matching beans were found in those locations the injection will fail.

In order for CDI injections to work, the test archive defined with ShrinkWrap must be a bean archive. That means adding beans.xml to the META-INF directory. Here's a @Deployment method that shows one way to add a beans.xml to the archive:

@Deployment

public static JavaArchive createTestArchive() {
   return ShrinkWrap.create("test.jar", JavaArchive.class)
      .addClass(NameOfClassUnderTest.class)
      .addAsManifestResource(new ByteArrayAsset(new byte[0]), Paths.create("beans.xml"))

In an application that takes full advantage of CDI, you can likely get by only using injections defined with the @Inject annotation. Regardless, the other two types of injection come in handy from time-to-time.

This chapter walks through the details of test execution, covering both the remote and local container cases.

Note

Whilst it's not necessary to understand the details of how Arquillian works, it is often useful to have some insight. This chapter gives you an overview of how Arquillian executes your test for you in your chosen container.

The question at this point is, how does Arquillian negotiate with the container to execute the test when the test framework is being invoked locally? Technially the mechanism is pluggable using another SPI, org.jboss.arquillian.spi.ContainerMethodExecutor. Arquillian provides a default implementation for remote servers which uses HTTP communication and an implementation for local tests, which works through direct execution of the test in the same JVM. Let's have a look at how the remote execution works.

The archive generator bundles and registers (in the web.xml descriptor) an HttpServlet, org.jboss.arquillian.protocol.servlet.ServletTestRunner, that responds to test execution GET requests. The test runner on the client side delegates to the org.jboss.arquillian.spi.ContainerMethodExecutor SPI implementation, which originates these test execution requests to transfer control to the container JVM. The name of the test class and the method to be executed are specified in the request query parameters named className and methodName, respectively.

When the test execution request is received, the servlet delegates to an implementation of the org.jboss.arquillian.spi.TestRunner SPI, passing it the name of the test class and the test method. TestRunner generates a test suite dynamically from the test class and method name and runs the suite (now within the context of the container).

The ServletTestRunner translates the native test result object of JUnit or TestNG into a org.jboss.arquillian.spi.TestResult and passes it back to the test executor on the client side by serializing the translated object into the response. The object gets encoded as either html or a serialized object, depending on the value of the outputMode request parameter that was passed to the servlet. Once the result has been transfered to the client-side test runner, the testing framework (JUnit or TestNG) wraps up the run of the test as though it had been executed in the same JVM.

Now you should have an understanding for how tests can be executed inside the container, but still be executed using existing IDE, Ant and Maven test plugins without any modification. Perhaps you have even started thinking about ways in which you can enhance or extend Arquillian. But there's still one challenge that remains for developing tests with Arquillian. How do you debug test? We'll look at how to hook a debugger into the test execution process in the next chapter.

So far, we've focused on testing your application internals, but we also want to test how others (people, or other programs) interact with the application. Typically, you want to make sure that every use case and execution path is fully tested. Third parties can interact with your application in a number of ways, for example web services, remote EJBs or via http. You need to check that you object serialization or networking work for instance.

This is why Arquillian comes with two run modes, in container and as client. in container is to test your application internals and as client is to test how your application is used by clients. Lets dive a bit deeper into the differences between the run modes and see how they effect your test execution and packaging.

While Arquillian tests can be easily executing using existing IDE, Ant and Maven test plugins, debugging tests are not as straightforward (but by no means difficult). The extra steps documented in this chapter are only relevant for tests which are not executed in the same JVM as the test runner. These steps to not apply to tests that are run in a local bean container (e.g., Weld SE), which can be debugged just like any other unit test.

We'll assume in this chapter that you are already using Eclipse and you already have the test plugin installed for the testing framework you are using (JUnit or TestNG).

If you set a break point and execute the test in debug mode using a remote container, your break point won't be hit. That's because when you debug an in-container test, you're actually debugging the container. The test runner and the test are executing in different JVMs. Therefore, to setup debugging, you must first attach the IDE debugger to the container, then execute the test in debug mode (i.e., debug as test). That puts the debugger on both sides of the fence, so to speak, and allows the break point to be discovered.

Let's begin by looking at how to attach the IDE debugger to the container. This isn't specific to Arquillian. It's the same setup you would use to debug a deployed application.

Just because the Arquillian project uses Maven doesn't mean you have to use it to run your Arquillian tests. Arquillian is designed to have seamless integration with JUnit and TestNG without any necessary test framework configuration. That means you can use any build system that has a JUnit or TestNG task to execute your Arquillian test cases. Since most of this guide focuses on using Arquillian in a Maven build, this chapter is going to be about alternative build systems, namely Gradle and Ant.

The secret ingredient required to activate the Arquillian test runner is getting the correct libraries on the classpath. (Often easier said than done). The libraries consist of the Arquillian container integration and the container runtime (for an embedded container) or deployment client (for a remote container).

In general, the steps to incorporate Arquillian into a build, regardless of what build tool you are using, can be summarized as:

If you are only running the Arquillian tests on a single container, this setup is exceptionally straightforward. The challenge comes when you want to run the tests on multiple containers. It's really just a matter of putting the correct libraries on the test classpath, though.

For some build systems, isolating multiple classpath definitions is more tricky than others. For instance, in Maven, you only get one test classpath per run (without using really advanced plugin configuration). You can toggle between different test classpath pairings through the use of profiles. Each profile contains the libraries for a single target container (a combination of the libraries itemized in steps 2 and 3 above). You'll see this strategy used in the Arquillian examples.

Other build tools, such as Gradle, can easily define new test tasks that each have their own, unique classpath. This makes it not only possible to separate out the target containers, but also run the tests against each one in the same build execution. We'll see an example of that later in this chapter. Gradle can also emulate the Maven profile strategy through the use of build fragment imports. We'll also show an example of that approach for contrast.

Gradle is a build tool that allows you to create declarative, maintainable, concise and highly-performing builds. More importantly, in this context, Gradle gives you all the freedom you need instead of imposing a rigid build lifecycle on you. You'll get a glimpse of just how flexible Gradle can be by learning how to integrate Arquillian into a Gradle build.

We'll be contrasting two strategies for running Arquillian tests from Gradle:

  1. Container-specific test tasks

  2. Test "profiles" via build fragment imports

The first strategy is the recommended one since it gives you the benefit of being able to run your tests on multiple containers in the same build. However, the second approach is less esoteric and will be more familiar to Maven users. Of course, Gradle is so flexible that there are likely other solutions for this problem. We invite you to give us feedback if you find a better way (or another way worth documenting).

Let's get the common build stuff out of the way, then dive into the two strategies listed above.

The simplest Gradle build for a Java project is a sparse one line.

apply plugin: JavaPlugin

Put this line into a file named build.gradle at the root of the project, which is the standard location of the Gradle build file. (Perhaps after seeing this configuration you'll understand the reference in the section title).

Next we'll add the Maven Central and JBoss Community repository definitions, so that we can pull down dependent libraries. The latter repository hosts the Arquillian artifacts.

apply plugin: JavaPlugin

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

If your SCM (e.g., SVN, Git) is already ignoring the target directory, you may want to move the Gradle build output underneath this folder, rather than allowing Gradle to use it's default build directory, build. Let's add that configuration to the common build logic as well:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

We also recommend that you centralize version numbers at the top of your build to make upgrading your dependency easy. This list will grow as you add other containers, but we'll seed the list for the examples below:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

...

We also need to add the unit test library (JUnit or TestNG) and the corresponding Arquillian integration:

dependencies {
   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian
}

In this example, we'll assume the project is compiling against APIs that are provided by the target container runtime, so we need to add a dependency configuration (aka scope) to include libraries on the compile classpath but excluded from the runtime classpath. In the future, Gradle will include support for such a scope. Until then, we'll define one ourselves in the configurations closure.

configurations {
   compileOnly
}

We also need to add the dependencies associated with that configuration to the compile classpaths using the sourceSets closure:

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Here's the Gradle build all together now:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha3', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Now that the foundation of a build is in place (or you've added these elements to your existing Gradle build), we are ready to configuring the container-specific test tasks. In the first approach, we'll create a unique dependency configuration and task for each container.

Each project in Gradle is made up of one or more tasks. A task represents some atomic piece of work which a build performs. Examples include compiling classes, executing tests, creating a JAR, publishing an artifact to a repository. We are interested in the executing tests task. But it's not necessarily just a single test task. Gradle allows you to define any number of test tasks, each having its own classpath configuration. We'll use this to configure test executions for each container.

Let's assume that we want to run the tests against the following three Arquillian-supported containers:

We'll need three components for each container:

We'll start with the Weld EE Embedded container. Starting from the Gradle build defined in the previous section, we first define a configuration for the test runtime dependencies.

configurations {
   compileOnly
   weldEmbeddedTestRuntime { extendsFrom testRuntime }
}

Next we add the dependencies for compiling against the Java EE API and running Arquillian tests in the Weld EE Embedded container:

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian

   // temporarily downgrade the weld-ee-embedded-1.1 container
   weldEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   weldEmbeddedTestRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   weldEmbeddedTestRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   weldEmbeddedTestRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   weldEmbeddedTestRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j
}

Finally, we define the test task:

task weldEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.weldEmbeddedTestRuntime
}

This task will execute in the lifecycle setup by the Java plugin in place of the normal test task. You run it as follows:

gradle weldEmbeddedTest

Or, more simply:

gradle wET

Now we just repeat this setup for the other containers.

Here's the full build file with the tasks for our three target containers:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/repositories/deprecated'
}

configurations {
   compileOnly
   weldEmbeddedTestRuntime { extendsFrom testRuntime }
   jbossasRemoteTestRuntime { extendsFrom testRuntime, compileOnly }
   glassfishEmbeddedTestRuntime { extendsFrom testRuntime }
}

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian

   // temporarily downgrade the weld-ee-embedded-1.1 container
   weldEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   weldEmbeddedTestRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   weldEmbeddedTestRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   weldEmbeddedTestRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   weldEmbeddedTestRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j

   jbossasRemoteTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-jbossas-remote-6', version: libraryVersions.arquillian
   jbossasRemoteTestRuntime group: 'org.jboss.jbossas', name: 'jboss-as-server', classifier: 'client', version: libraryVersions.jbossas, transitive: false
   jbossasRemoteTestRuntime group: 'org.jboss.jbossas', name: 'jboss-as-profileservice', classifier: 'client', version: libraryVersions.jbossas

   glassfishEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-glassfish-embedded-3', version: libraryVersions.arquillian
   glassfishEmbeddedTestRuntime group: 'org.glassfish.extras', name: 'glassfish-embedded-all', version: libraryVersions.glassfish
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

task weldEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.weldEmbeddedTestRuntime
}

task jbossasRemoteTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + files('src/test/resources-jbossas') + configurations.jbossasRemoteTestRuntime
}

task glassfishEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.glassfishEmbeddedTestRuntime
}

It's now possible to run the Arquillian tests against each of the three containers in sequence using this Gradle command (make sure a JBoss AS is started in the background):

gradle weldEmbeddedTest jbossasRemoteTest glassfishEmbeddedTest

Pretty cool, huh?

Now let's look at another way to solve this problem.

Another way to approach integrating Arquillian into a Gradle build is to emulate the behavior of Maven profiles. In this case, we won't be adding any extra tasks, rather overriding the Java plugin configuration and provided tasks.

Once again, let's assume that we want to run the tests against the following three Arquillian-supported containers:

All we need to do is customize the test runtime classpath for each container. First, let's setup the common compile-time dependencies in the main build file:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha3', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

dependencies {
   group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

We then need to create a partial Gradle build file for each container that contains the container-specific dependencies and configuration. Let's start with Weld EE Embedded.

Create a file named weld-ee-embedded-profile.gradle and populate it with the following contents:

dependencies {
   // temporarily downgrade the weld-ee-embedded-1.1 container
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   testRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   testRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   testRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   testRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j
}

Here's the partial build file for Remote JBoss AS, named jbossas-remote-profile.gradle:

dependencies {
   testRuntime group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-jbossas-remote-6', version: libraryVersions.arquillian
   testRuntime group: 'org.jboss.jbossas', name: 'jboss-as-server', classifier: 'client', version: libraryVersions.jbossas, transitive: false
   testRuntime group: 'org.jboss.jbossas', name: 'jboss-as-profileservice', classifier: 'client', version: libraryVersions.jbossas
}

test {
   classpath = sourceSets.test.classes + sourceSets.main.classes + files('src/test/resources-jbossas') + configurations.testRuntime
}
And finally the one for Embedded GlassFish, named glassfish-embedded-profile.gradle:
dependencies {
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-glassfish-embedded-3', version: libraryVersions.arquillian
   testRuntime group: 'org.glassfish.extras', name: 'glassfish-embedded-all', version: libraryVersions.glassfish
}

Now we need to import the appropriate partial Gradle build into the main build. The file will be selected based on the value of the project property named profile.

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

apply from: profile + '-profile.gradle'

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Tests are run in the Weld EE Embedded runtime using this command:

gradle test -Pprofile=weld-ee-embedded

That's pretty much the same experience you get when you use Maven (and a whole heck of a lot simpler).

While the configuration is much simpler using the profiles strategy, there are two things to keep in mind:

If you have a better idea of how to integrate an Arquillian test suite into a Gradle build, we'd love to hear it on the Arquillian discussion forums.

See the CDI subproject of the Arquillian showcase for an Ant+Ivy build example until this section is written.

This chapter walks through some more advanced features and use cases you can have Arquillian do for you.

There are times when you need to involve multiple containers in the same test case, if you for instance want to test clustering. The first step you need to take is to add a group with multiple containers to your Arquillian configuration.


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <group qualifier="tomcat-cluster">
        <container qualifier="container-1" default="true">
            <configuration>
                <property name="tomcatHome">target/tomcat-embedded-6-standby</property>
                <property name="workDir">work</property>
                <property name="bindHttpPort">8880</property>
                <property name="unpackArchive">true</property>
            </configuration>
            <dependencies>
                <dependency>org.jboss.arquillian.container:arquillian-tomcat-embedded-6:1.0.0-SNAPSHOT</dependency>
                <dependency>org.apache.tomcat:catalina:6.0.29</dependency>
                <dependency>org.apache.tomcat:coyote:6.0.29</dependency>
                <dependency>org.apache.tomcat:jasper:6.0.29</dependency>
            </dependencies>
        </container>
        <container qualifier="container-2">
            <configuration>
                <property name="tomcatHome">target/tomcat-embedded-6-active-1</property>
                <property name="workDir">work</property>
                <property name="bindHttpPort">8881</property>
                <property name="unpackArchive">true</property>
            </configuration>
            <dependencies>
                <dependency>org.jboss.arquillian.container:arquillian-tomcat-embedded-6:1.0.0-SNAPSHOT</dependency>
                <dependency>org.apache.tomcat:catalina:6.0.29</dependency>
                <dependency>org.apache.tomcat:coyote:6.0.29</dependency>
                <dependency>org.apache.tomcat:jasper:6.0.29</dependency>
            </dependencies>
        </container>
    </group>
</arquillian>

So what we have done here is to say we have two containers that Arquillian will control, container-1 and container-2. Arquillian will now instead of starting up one container, which is normal, start up two. In your test class you can target different deployments against the different containers using the @TargetsContainer("containerName") annotation on your Deployment methods.

@Deployment(name = "dep1") @TargetsContainer("container-1")

public static WebArchive createDep1() {}
@Deployment(name = "dep2")  @TargetsContainer("container-2")
public static WebArchive createDep2() {}
@Test @OperateOnDeployment("dep1")
public void testRunningInDep1() {}
@Test @OperateOnDeployment("dep2")
public void testRunningInDep2() {}

We now have a single test class that will be executed in two different containers. testRunningInDep1 will operate in the context of the dep1 deployment which is deployed on the container named container-1 and testRunningInDep2 will operate in the context of deployment dep2 which is deployed on container container-2. As the test moves along, each method is executed inside the individual containers.

The performance extension to Arquillian is a simple way of checking that the code you want to test performs within the range you want it to. It's can also automatically catch any performance regressions that might be added to your applications. - and as Arquillian itself, its very easy to use.



// include other arquillian imports here...
import org.jboss.arquillian.performance.annotation.Performance;
import org.jboss.arquillian.performance.annotation.PerformanceTest;
@PerformanceTest(resultsThreshold=2)
@RunWith(Arquillian.class)
public class WorkHardCdiTestCase
{
   @Deployment
   public static JavaArchive createDeployment() {
       return ShrinkWrap.create(JavaArchive.class ,"test.jar")
               .addPackage( WorkHard.class.getPackage())
               .addAsManifestResource(
                       EmptyAsset.INSTANCE,
                       ArchivePaths.create("beans.xml"));
   }
   
   @Inject HardWorker worker;
   
   @Test
   @Performance(time=20)
   public void doHardWork() throws Exception 
   {
      Assert.assertEquals(21, worker.workingHard(), 0d);
   }
}
    

As you can see the only two additions needed are @Performance and @PerformanceTest. They do different things and can be used seperately or combined.

@Performance require one argument, time (a double) which set the required maximum time that the test is allowed to spend in milliseconds. If the test exceeds that time it will fail with an exception explaining the cause.

@PerformanceTest will cause every testrun of that test to be saved and every new run will compare results with previous runs. If the new testrun exceeds the previous runs with a defined threshold an exception will be thrown. The threshold can be set with the parameter resultsThreshold. It is by default set to 1d.

How threshold is calculated: resultsThreshold * newTime < oldTime.

The only extra dependency needed is to add arquillian-performance to your pom.xml. Take a look at the Chapter 3, Getting started to see how you set up arquillian using maven.


<dependency>
   <groupId>org.jboss.arquillian.extension</groupId>
   <artifactId>arquillian-performance</artifactId>
   <version>${arquillian.version}</version>
   <scope>test</scope>
</dependency>
    

The JSFUnit integration to Arquillian is a simpler way of using JSFUnit.

The only dependencies needed is to add org.jboss.arquillian.framework:arquillian-framework-jsfunit and org.jboss.jsfunit:jboss-jsfunit-core to your pom.xml. The rest is handled by Arquillian in the background. Take a look at the Chapter 3, Getting started to see how you set up arquillian using maven.


<dependency>
   <groupId>org.jboss.arquillian.framework</groupId>
   <artifactId>arquillian-framework-jsfunit</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.jboss.jsfunit</groupId>
   <artifactId>jboss-jsfunit-core</artifactId>
   <version>1.3.0.Final</version>
   <scope>test</scope>
</dependency>
    

Warning

To use JSFUnit with Arquillian, JSFUnit 1.3.0.Final is required.

The Arquillian Drone extension for Arquillian provides a simple way of including functional tests for your web based application. Arquillian Drone manages the life cycle of web testing tool, which is either Arquillian Ajocado, Selenium or WebDriver. Arquillian Drone automatically manages life cycle of objects required for interaction between browser and deployed application.

Following example illustrates how Arquillian Drone can be used with Arquillian Ajocado. This example is a part of Arquillian Drone test classes, so you are free to experiment with it. Arquillian Ajocado is a Selenium on steroids, because it provides type safe API over classic DefaultSelenium object, has extended support for handling AJAX based UI and adds pretty fast JQuery locators to you browser, so your test are executed faster. If you are not experienced with Arquillian Ajocado, you can still use DefaultSelenium or WebDriver specific browser, such as FirefoxDriver. The beauty of Arquillian Drone is that is supports all of them and their usage is pretty much the same.

package org.jboss.arquillian.drone.example;


import static org.jboss.arquillian.ajocado.Ajocado.elementPresent;
import static org.jboss.arquillian.ajocado.Ajocado.waitModel;
import static org.jboss.arquillian.ajocado.guard.request.RequestTypeGuardFactory.waitHttp;
import static org.jboss.arquillian.ajocado.locator.LocatorFactory.id;
import static org.jboss.arquillian.ajocado.locator.LocatorFactory.xp;
import java.net.URL;
import org.jboss.arquillian.ajocado.framework.AjaxSelenium;
import org.jboss.arquillian.ajocado.locator.IdLocator;
import org.jboss.arquillian.ajocado.locator.XpathLocator;
import org.jboss.arquillian.api.Run;
import org.jboss.arquillian.drone.annotation.ContextPath;
import org.jboss.arquillian.drone.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
 * Tests Arquillian Drone extension against Weld Login example. * 
 * Uses Ajocado driver bound to Firefox browser.
 * 
 */
@RunWith(Arquillian.class)
public class AjocadoTestCase extends AbstractTestCase
{
   // load ajocado driver
   @Drone
   AjaxSelenium driver;
   // Load context path to the test
   @ContextPath
   URL contextPath;
   protected XpathLocator LOGGED_IN = xp("//li[contains(text(),'Welcome')]");
   protected XpathLocator LOGGED_OUT = xp("//li[contains(text(),'Goodbye')]");
   protected IdLocator USERNAME_FIELD = id("loginForm:username");
   protected IdLocator PASSWORD_FIELD = id("loginForm:password");
   protected IdLocator LOGIN_BUTTON = id("loginForm:login");
   protected IdLocator LOGOUT_BUTTON = id("loginForm:logout");
   @Deployment(testable=false)
   public static WebArchive createDeployment()
   {
      return ShrinkWrap.create(WebArchive.class, "weld-login.war")
            .addClasses(Credentials.class, LoggedIn.class, Login.class, User.class, Users.class)            
            .addAsWebInfResource(new File("src/test/webapp/WEB-INF/beans.xml"))
            .addAsWebInfResource(new File("src/test/webapp/WEB-INF/faces-config.xml"))            
            .addAsWebInfResource(new File("src/test/resources/import.sql"))
            .addAsWebResource(new File("src/test/webapp/index.html"))
            .addAsWebResource(new File("src/test/webapp/home.xhtml"))
            .addAsWebResource(new File("src/test/webapp/template.xhtml"))
            .addAsWebResource(new File("src/test/webapp/users.xhtml"))
            .addAsResource(new File("src/test/resources/META-INF/persistence.xml"), ArchivePaths.create("META-INF/persistence.xml"))
            .setWebXML(new File("src/test/webapp/WEB-INF/web.xml"));
   }
   @Test
   public void testLoginAndLogout()
   {
      driver.open(contextPath);
      waitModel.until(elementPresent.locator(USERNAME_FIELD));      
      Assert.assertFalse("User should not be logged in!", driver.isElementPresent(LOGOUT_BUTTON));
      driver.type(USERNAME_FIELD, "demo");
      driver.type(PASSWORD_FIELD, "demo");
      
      waitHttp(driver).click(LOGIN_BUTTON);
      Assert.assertTrue("User should be logged in!", driver.isElementPresent(LOGGED_IN));
      
      waitHttp(driver).click(LOGOUT_BUTTON);
      Assert.assertTrue("User should not be logged in!", driver.isElementPresent(LOGGED_OUT));
   }
}

As you can see, execution does not differ from common Arquillian test much. The only requirement is actually running Arquillian in client mode, which is enforced by marking deployment as utestable = false or alternatively by @RunAsClient annotation. The other annotations present in the test are used to inject web test framework instance (@Drone) and context path (@ContextPath) for deployed archive into your test. Their life cycle is completely managed by Arquillian Drone, as described in Section 11.3.3, “Life cycle of @Drone objects”. The instance is used in test method to traverse UI of application via Firefox browser, fill user credentials and signing up and out. Test is based on JUnit, but Arquillian Drone, as well as the rest of Arquillian supports TestNG as well.


This combination matrix is tested and known to work. However, we expect that all WebDriver interface based browsers will work. Arquillian Drone does not force you to use a specific version of web framework test implementation, so feel free to experiment with it.

Arquillian Drone requires a few test dependencies which are marked as provided to let you choose their versions. Add following code into your Maven dependecies to enable Arquillian Drone functionality in your test cases.


<!-- Arquillian Drone dependency -->
<dependency>
   <groupId>org.jboss.arquillian.extension</groupId>
   <artifactId>arquillian-drone</artifactId>
   <version>${arquillian.version}</version>
   <scope>test</scope>
</dependency>

<!-- Arquillian Ajocado dependencies -->
<dependency>
   <groupId>org.jboss.arquillian.ajocado</groupId>
   <artifactId>arquillian-ajocado-api</artifactId>
   <version>${version.ajocado}</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.jboss.arquillian.ajocado</groupId>
   <artifactId>arquillian-ajocado-impl</artifactId>
   <version>${version.ajocado}</version>
   <scope>test</scope>
</dependency>

<!-- Selenium (including WebDriver in 2.x versions) -->
<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-remote-control</artifactId>
   <version>${version.selenium}</version>
   <scope>test</scope>        
</dependency>
<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-server</artifactId>
   <version>${version.selenium}</version>
   <scope>test</scope>
</dependency>
      
<!-- required to run Selenium Server, needed if you want Arquillian Drone to start Selenium Server for you -->
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-simple</artifactId>  <!-- choose different underlying implementation if you want -->
   <version>${version.slf4j}</version>  <!-- up to you, tested with 1.5.10 -->
   <scope>test</scope>
</dependency>

@Drone instances are automatically configured from arquillian.xml descriptor file, with possibility of overridding arquillian.xml configuration by system properties. Every type of @Drone instance has its own configuration namespace, although namespace overlap in areas where it makes sense, such as sharing a part of configuration between Selenium and Selenium server. System properties always take precedence.

If you are using @Qualifiers, you can use them to modify configuration, such as create a special configuration for a method based life cycle browser.


Arquillian Ajocado uses ajacodo namespace. This means, you can define properties either in arquillian.xml


<extension qualifier="ajocado">
   <configuration>
      <property name="seleniumHost">myhost.org</property>
   </configuration>
</extension>

Or you can convert property name to name of system property, using following formula arqullian. + (namespace) + . + (property name converted to dotted lowercase). For instance, seleniumNetworkTrafficEnabled will be converted to arquillian.ajocado.selenium.network.traffic.enabled System property name.


Selenium uses selenium namespace.


WebDriver uses webdriver namespace.


Selenium Server uses selenium-server namespace.

Warning

Please note that non-letter characters are converted to dots, so for instance to enable Selenium via System property, you have to set arquillian.selenium.server.enable to true.

Selenium Server has different life cycle than @Drone instance, it is created and started before test suite and disposed after test suite. If you have your own Selenium Server instance running, you simply omit its configuration, however specifying it is the simplest way how to start it and have it managed by Arquillian.

If you are wondering how to define configuration for @Qualifier @Drone instance, it's very easy. Only modification you have to do is to change namespace to include - (@Qualifier annotation name converted to lowercase). Please note, that for System properties are all non-letter characters converted to dots. For instance, if you qualified Arquillian Ajocado instance with @MyExtraBrowser, its namespace will become ajocado-myextrabrowser.

The namespace resolution is a bit more complex. Arquillian Drone will search for configuration in following order:

  1. Search for the exact match of namespace (e.g. ajocado-myextrabrowser) in arqullian.xml, if found, step 2 is not performed

  2. Search for a match of base namespace, without qualifier (e.g. ajocado) in arqullian.xml

Then System property overriddes are applied in the same fashion.

The big advantage of Arquillian Drone extension is its flexibility. We provide you reasonable defaults, but if they are not sufficient or if they do not fulfill your needs, you can change them. You can change behaviour of existing implemenation or implement support for your own testing framework. See JavaDoc/sources for more details, here is an enumeration of classes you should focus on:

The import note is that implemenation of Configurator, Instantiator and Destructor are searched on the class path and they are sorted according to precedence they declare. Arquillian Ajocado default implemenation has precedence of 0, so if your implementation has bigger precedence and instantiates type T with configuration C, Arquillian Drone will use it. This provides you the ultimate way how to change behavior if desired. Of course, you can provide support for your own framework in the very same way, so in your test you can use @Drone annotation to manage instance of arbitrary web testing framework.

Arquillian Drone SPI extensions are searched via descriptions in META-INF/services on class path. For instance, to override DefaultSelenium instantiator, create file META-INF/services/org.jboss.arquillian.drone.spi.Instantiator with following content:

fully.quallified.name.of.my.implementation.Foo

Your class Foo must implement Instantiator<DefaultSelenium,SeleniumConfiguration> interface.

A DeployableContainer implementation that can connect and run against a remote(different JVM, different machine) running JBoss AS 5 instance. This implementation has no lifecycle support, so it can not be started or stopped.


Example of Maven profile setup


<profile>
    <id>jbossas-remote-5</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-remote-5</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>5.0.1.GA</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can connect and run against a remote(different JVM, different machine) running JBoss AS 5.1 instance. This implementation has no lifecycle support, so it can not be started or stopped.


Example of Maven profile setup


<profile>
    <id>jbossas-remote-5.1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-remote-5.1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>5.1.0.GA</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a remote(different JVM, same machine) JBoss AS 5.1 instance. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Example of Maven profile setup


<profile>
    <id>jbossas-managed-5.1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-managed-5.1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-server-manager</artifactId>
            <version>1.0.3.GA</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>5.1.0.GA</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can connect and run against a remote(different JVM, different machine) running JBoss AS 6.0 instance. This implementation has no lifecycle support, so it can not be started or stopped.


Example of Maven profile setup


<profile>
    <id>jbossas-remote-6</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-remote-6</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>6.0.0.Final</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a remote(different JVM, same machine) JBoss AS 6.0 instance. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Example of Maven profile setup


<profile>
    <id>jbossas-managed-6</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-managed-6</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-server-manager</artifactId>
            <version>1.0.3.GA</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-client</artifactId>
            <version>6.0.0.Final</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) JBoss AS 6.0 instance. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Example of Maven profile setup


<profile>
    <id>jbossas-embedded-6</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jbossas-embedded-6</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.jbossas</groupId>
            <artifactId>jboss-as-depchain</artifactId>
            <version>6.0.0.Final</version>
            <type>pom</type>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.jbossas</groupId>
                <artifactId>jboss-as-depchain</artifactId>
                <version>6.0.0.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <additionalClasspathElements>
                        <additionalClasspathElement>${env.JBOSS_HOME}/client/jbossws-native-client.jar</additionalClasspathElement>
                        <!--
                            Because jbossweb.sar contains shared web.xml, which must be
                            visible from same CL as TomcatDeployer.class.getClassLoader
                        -->
                        <additionalClasspathElement>${env.JBOSS_HOME}/server/default/deploy/jbossweb.sar</additionalClasspathElement>
                    </additionalClasspathElements>

                    <redirectTestOutputToFile>true</redirectTestOutputToFile>
                    <trimStackTrace>false</trimStackTrace>
                    <printSummary>true</printSummary>
                    <forkMode>once</forkMode>

                    <!--
                        MaxPermSize Required to bump the space for relective data like
                        classes, methods, etc. EMB-41. Endorsed required for things like
                        WS support (EMB-61)
                    -->
                    <argLine>-Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Djava.endorsed.dirs=${env.JBOSS_HOME}/lib/endorsed -Djboss.home=${env.JBOSS_HOME} -Djboss.boot.server.log.dir=${env.JBOSS_HOME}</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) GlassFish 3.1 instance. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Example of Maven profile setup


<profile>
    <id>glassfish-embedded-3.1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-embedded-3</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.extras</groupId>
            <artifactId>glassfish-embedded-all</artifactId>
            <version>3.1</version>
        </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that manages the complete lifecycle of an embedded (same JVM) Tomcat 6 Servlet Container. (Keep in mind that only select EE APIs are available in Tomcat 6, such as JNDI and Servlet 2.5). Test archives are adapted to Tomcat's StandardContext API by ShrinkWrap and deployed programmatically.


Warning

CDI support requires use of Weld Servlet and associated configuration. The WAR will have to be unpacked as well in order for Weld to locate the classes. See the following configuration example.
<?xml version="1.0" encoding="UTF-8"?> 
<arquillian xmlns="http://jboss.com/arquillian" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:tomcat6="urn:arq:org.jboss.arquillian.container.tomcat.embedded_6"> 

  <tomcat6:container> 
      <!-- unpackArchive must be true if using the Weld Servlet module --> 
  <tomcat6:unpackArchive>true</tomcat6:unpackArchive> 
</tomcat6:container> 

</arquillian>

Running an in-container test on Tomcat 6 currently requires that you add the Arquillian Protocol Servlet to the test archive's web.xml, a temporary measure until ARQ-217 is resolved. The listing below shows a minimum web.xml containing the required Servlet mapping:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

   <servlet>
      <servlet-name>ServletTestRunner</servlet-name>
      <servlet-class>org.jboss.arquillian.protocol.servlet_3.ServletTestRunner</servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>ServletTestRunner</servlet-name>
      <url-pattern>/ArquillianServletRunner</url-pattern>
   </servlet-mapping>

</web-app>

If you forget to add this Servlet mapping for a test using the in-container run mode, you will get a failure with the message "Kept getting 404s" because Arquillian can't communicate with the deployed application.

Example of Maven profile setup


<profile>
    <id>tomcat-embedded</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-tomcat-embedded-6</artifactId>
            <version>1.0.0-SNAPSHOT</version>
         <scope>test</scope>
        </dependency>
      <dependency>
         <groupId>org.apache.tomcat</groupId>
         <artifactId>catalina</artifactId>
         <version>6.0.29</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.apache.tomcat</groupId>
         <artifactId>coyote</artifactId>
         <version>6.0.29</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.apache.tomcat</groupId>
         <artifactId>jasper</artifactId>
         <version>6.0.29</version>
         <scope>provided</scope>
      </dependency>
      <!-- Weld servlet, EL and JSP required for testing CDI injections -->
      <dependency>
         <groupId>org.jboss.weld.servlet</groupId>
         <artifactId>weld-servlet</artifactId>
         <version>1.0.1-Final</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.glassfish.web</groupId>
         <artifactId>el-impl</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>jsp-api</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a embedded (same JVM) Jetty 6.1 Servlet Container. The minimum recommended version is Jetty 6.1.12, though you can use an earlier 6.1 version if you aren't using JNDI resources. Only select EE APIs are available, such as JNDI and Servlet 2.5. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

CDI support requires use of Weld Servlet.

Example of Maven profile setup


<profile>
    <id>jetty-embedded</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jetty-embedded-6.1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
         <scope>test</scope>
        </dependency>
      <dependency>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>jetty</artifactId>
         <version>6.1.12</version>
         <scope>test</scope>
      </dependency>
      <!-- plus and naming requires for using JNDI -->
      <dependency>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>jetty-plus</artifactId>
         <version>6.1.12</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>jetty-naming</artifactId>
         <version>6.1.12</version>
         <scope>test</scope>
      </dependency>
      <!-- Weld servlet, EL and JSP required for testing CDI injections -->
      <dependency>
         <groupId>org.jboss.weld.servlet</groupId>
         <artifactId>weld-servlet</artifactId>
         <version>1.0.1-Final</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.glassfish.web</groupId>
         <artifactId>el-impl</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>jsp-api</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a embedded (same JVM) Jetty 7 Servlet Container. Only select EE APIs are available, such as JNDI and parts of Servlet (support for web-fragement.xml is the important bit). This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

CDI support requires use of Weld Servlet.

Example of Maven profile setup


<profile>
    <id>jetty-embedded</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-jetty-embedded-7</artifactId>
            <version>1.0.0-SNAPSHOT</version>
         <scope>test</scope>
        </dependency>
      <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-webapp</artifactId>
         <version>7.0.2.v20100331</version>
         <scope>test</scope>
      </dependency>
      <!-- plus and naming requires for using JNDI -->
      <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-plus</artifactId>
         <version>7.0.2.v20100331</version>
         <scope>test</scope>
      </dependency>
      <!-- Weld servlet, EL and JSP required for testing CDI injections -->
      <dependency>
         <groupId>org.jboss.weld.servlet</groupId>
         <artifactId>weld-servlet</artifactId>
         <version>1.0.1-Final</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.glassfish.web</groupId>
         <artifactId>el-impl</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>jsp-api</artifactId>
         <version>2.2</version>
         <scope>test</scope>
      </dependency>
    </dependencies>
</profile>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) Weld(CDI reference implementation) SE edition. No EE APIs are available. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

Local EJBs only, which get treated as managed beans. Transactions, security and EJB context injection are not applied.

Example of Maven profile setup


<profile>
    <id>weld-se-embedded-1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-weld-se-embedded-1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.weld</groupId>
                <artifactId>weld-core-bom</artifactId>
                <version>1.0.1-SP1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</profile>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) Weld(CDI reference implementation) SE edition. No EE APIs are available. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

Local EJBs only, which get treated as managed beans. Transactions, security and EJB context injection are not applied.

Example of Maven profile setup


<profile>
    <id>weld-se-embedded-11</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-weld-se-embedded-1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.weld</groupId>
                <artifactId>weld-core-bom</artifactId>
                <version>1.1.0.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</profile>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) Weld(CDI reference implementation) EE version. Mock EE APIs are available. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

Local EJBs only, which get treated as managed beans. Transactions, security and EJB context injection are not applied.

Example of Maven profile setup


<profile>
    <id>weld-ee-embedded-1.1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-weld-ee-embedded-1.1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.weld</groupId>
                <artifactId>weld-core-bom</artifactId>
                <version>1.1.0.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</profile>

To run Weld EE Embedded you also need the Java EE APIs. These APIs might be provided to you by other dependencies like org.jboss.jbossas:jboss-as-client, org.jboss.spec:jboss-javaee-6.0 or org.glassfish.extras:glassfish-embedded-all.


<dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.1.2-b04</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>org.jboss.spec.javax.servlet</groupId>
    <artifactId>jboss-servlet-api_3.0_spec</artifactId>
    <version>1.0.0.Beta2</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>jta</artifactId>
    <version>1.1</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>org.jboss.ejb3</groupId>
    <artifactId>jboss-ejb3-api</artifactId>
    <version>3.1.0</version>
    <scope>test</scope>
 </dependency>

A DeployableContainer implementation that can run and connect to a embedded(same JVM) WeldApache OpenWebBeans(CDI) instance. No EE APIs are available. This implementation has lifecycle support, so the container will be started and stopped as part of the test run.


Warning

Local EJBs only, which get treated as managed beans. Transactions, security and EJB context injection are not applied.

Example of Maven profile setup


<profile>
    <id>openwebbeans-embedded-1</id>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-openwebbeans-embedded-1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-spi</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-impl</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-el_2.2_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jta_1.1_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-validation_1.0_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-interceptor_1.1_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jcdi_1.0_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-atinject_1.0_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-servlet_2.5_spec</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.openwebbeans</groupId>
                <artifactId>openwebbeans</artifactId>   
                <version>1.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</profile>