Getting started with Arquillian

Arquillian is a platform that simplifies integration testing for Java middleware. In this tutorial we will walk through the steps to set up an Arquillian project for Jakarta EE with Maven.

Arquillian in a nustshell

Arquillian minimizes the burden on you when coding Integration tests for Enterprise applications. Some of the highlights of Arquillian include:

  • Managing the life cycle of the container (start/stop)
  • Bundling the test class with the dependent classes and resources into a deployable archive
  • Enhancing the test class (for example, resolving @Inject, @EJB, and @Resource injections)
  • Deploying the archive to test applications (deploy/undeploy), and capturing results and failures

Enough with introductions, let’s get our hands dirty with a real example!

Setting up an Arquillian Project with Maven

To kickstart your Arquillian projects we recommend using on of the archetypes available on WildFly public repository on Nexus.

arquillian tutorial

For example, the wildfly-jakartaee-webapp-archetype which will set up a Web application with all the WildFly and Arquillian dependencies in place:

mvn archetype:generate -DgroupId=com.masterheboss -DartifactId=sample-jakartaee-webapp-archetype -Dversion=1.0-SNAPSHOT -DarchetypeGroupId=org.wildfly.archetype -DarchetypeArtifactId=wildfly-jakartaee-webapp-archetype -DarchetypeVersion=26.0.0.Final

Next, we will be coding a sample Test Class:

import java.util.List;
import java.util.UUID;

import javax.inject.Inject;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;

import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.mastertheboss.model.SimpleProperty;
import com.mastertheboss.producer.Producer;
import com.mastertheboss.ejb.ServiceBean;
import com.mastertheboss.repository.RepositoryManager;

@RunWith(Arquillian.class)
public class ServiceTest {
	@Deployment
	public static Archive<?> createTestArchive() {
		return ShrinkWrap.create(WebArchive.class, "test.war").addPackage(ServiceBean.class.getPackage())
				.addPackage(Producer.class.getPackage()).addPackage(SimpleProperty.class.getPackage())
				.addPackage(RepositoryManager.class.getPackage()).addAsResource("META-INF/persistence.xml")
				.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");

	}

	@Inject
	ServiceBean ejb;

	@Inject
	RepositoryManager repo;

	@Test
	public void testRegister() throws Exception {
		String key = UUID.randomUUID().toString();
		String value = UUID.randomUUID().toString();
		SimpleProperty p = new SimpleProperty();
		p.setKey(key);
		p.setValue(value);
		ejb.put(p);

		List<SimpleProperty> list = repo.queryCache();
		assert (list.size() > 0);

		assert (list.get(0).getKey().equals(key));

	}

}

The full source code for the Jakarta EE project is available at the end of this article. The purpose of this example is to insert a key/value pair using the ServiceBean EJB and then use the RepositoryManager class to query our data.
The first thing to notice, is the following annotation that tells JUnit to use Arquillian as the test controller:

@RunWith(Arquillian.class)
public class ArquillianTest {
}

Arquillian then looks for a static method with the @Deployment annotation; it creates a micro deployment, including all the resources, just as you would when packaging your applications with your favourite tool:

The fluent API provided by the ShrinkWrap project (http://www.jboss.org/shrinkwrap) makes this technique possible using the create method, which accepts the type of deployment unit (WebArchive) as the argument the deployment name (in our case, we will name it test-demo.war) and all the resources are included in this archive. In our case, instead of including all the single classes, we are using the addPackage utility method that adds all the classes available in a package.

Building the Arquillian test

Although Arquillian does not depend on a specific build tool, we recommend to use it with Maven; it offers dependency management and thus simplifies the task of including the Arquillian libraries in the application since they are distributed in the Central Maven repository.

The first thing that is necessary to include in order to run an Arquillian test is the JUnit dependency:

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

Next, if you want to test enterprise features such as EJB and the Java Transaction API (JTA), you need to include the org.jboss.arquillian.junit dependency as well:

<dependency>
 <groupId>org.jboss.arquillian.junit</groupId>
 <artifactId>arquillian-junit-container</artifactId>
 <scope>test</scope>
</dependency>

After that, since our Arquillian test uses a protocol to communicate with the server application, we will need to add the org.jboss.arquillian.protocol dependency (named so as it’s compatible with Servlet 2.5/3.0 specifications):

<dependency>
 <groupId>org.jboss.arquillian.protocol</groupId>
 <artifactId>arquillian-protocol-servlet</artifactId>
 <scope>test</scope>
</dependency>

Finally, we will now include two profiles into our configuration. You can use a Maven profile to create different target environments for our goals; in our case, we will create two profiles:
The first profile is named arq-managed; it will start a new WildFly instance and execute the test, shutting it down when done:

<profile>
   <!-- Run with: mvn clean test -Parq-managed -->
   <id>arq-managed</id>
   <dependencies>
      <dependency>
         <groupId>org.wildfly.arquillian</groupId>
         <artifactId>wildfly-arquillian-container-managed</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
</profile>

The second profile is named arq-remote; it will perform testing against a remote WildFly instance:

<profile>
   <!-- Run with: mvn clean test -Parq-remote -->
   <id>arq-remote</id>
   <dependencies>
      <dependency>
         <groupId>org.wildfly.arquillian</groupId>
         <artifactId>wildfly-arquillian-container-remote</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
</profile>

Running the Arquillian Test

Arquillian needs to know where WildFly is installed so that it can manage the lifecycle of the container using the startup script. You can configure the JBOSS HOME application into the arquillian.xml file as follows:

<arquillian xmlns="http://jboss.org/schema/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">

    <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most mature -->
    <defaultProtocol type="Servlet 3.0" />

    <!-- Uncomment to have test archives exported to the file system for inspection -->
    <!--<engine>
        <property name="deploymentExportPath">target/</property>
    </engine>-->

    <!-- Example configuration for a managed WildFly / JBoss EAP instance -->
    <container qualifier="managed">
        <!--<configuration>
            <property name="jbossHome">EAP_HOME</property>
        </configuration> -->
    </container>
    
    <!-- Example configuration for a remote WildFly / JBoss EAP instance -->
    <container qualifier="remote">
        <!-- Arquillian will deploy to this WildFly server. -->
        <configuration>
            <property name="managementAddress">127.0.0.1</property>
            <property name="managementPort">9990</property>
            <!-- If deploying to a remote server, you have to specify username/password here -->
            <!-- <property name="username">admin</property>
            <property name="password">admin</property> -->
        </configuration>
    </container>
</arquillian>

To set WildFly installation folder, uncomment the above property “jbossHome” with the correct location.

Otherwise, simply export this value in an environment variable:

export JBOSS_HOME=/home/jboss/wildfly-26.0.1.Final/

Running the Test with a managed container

This test will start a managed container, using the location available either in the configuration or in the JBOSS_HOME variable:

mvn test -Parq-managed

Verify that the Test completed successfully:

10:47:45,278 INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deployed "test.war" (runtime-name : "test.war")
. . . .
10:47:45,828 INFO  [org.jboss.as] (MSC service thread 1-4) WFLYSRV0050: WildFly Full 26.0.1.Final (WildFly Core 18.0.4.Final) stopped in 26ms

Results :

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

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.725 s
[INFO] Finished at: 2022-02-03T10:47:46+01:00
[INFO] ------------------------------------------------------------------------

Running Arquillian Test against a remote container

To run the test against a running WildFly instance, firstly start the server:

$ ./standalone.sh

In order to run it from a terminal execute:

mvn clean test -Parq-remote

Troubleshooting common Arquillian issues:

My Arquillian tests are not running!

It’s likely that you are using the surefire-maven-plugin. This plugin does not recognize tests that ends with *IT. You should change it’s name to *Test or use other technique.

I get the following error when launching the test: Caused by: java.lang.IllegalArgumentException: DeployableContainer must be specified

It’s likely that you have no active profile in your pom.xml. Activate the default Arquillian profile as in the following example:

<profile>
   <id>arq-wildfly-managed</id>
   <activation>
      <activeByDefault>true</activeByDefault>
   </activation>
   <dependencies>
      <dependency>
         <groupId>org.wildfly.arquillian</groupId>
         <artifactId>wildfly-arquillian-container-managed</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
</profile>

As an alternative, launch Maven selecting the profile you’re interested in:

mvn clean test -Parq-remote

Source code

The source code for this tutorial is available here: https://github.com/fmarchioni/mastertheboss/tree/master/arquillian/sample-jakartaee-webapp-archetype

If you want to learn how to run this example project from Eclipse IDE, check out this article: Running Arquillian Tests from Eclipse

Found the article helpful? if so please follow us on Socials