Running Arquillian test using different TomEE/OpenEJB adapters in the same build/artifact


Arquillian is a really great testing tool but it only supports to find one adapter (link to the container) in the classpath.

The bad side of this kind of limitation appears when you write a simple application. Let say a single war. Why would you create some more modules just to put your tests? I know it is a standard maven solution but it doesn’t sound really great since IMO one artifact should mean something for the application (that’s purely personal and i understand choices can be different).

This is particularly true when you use OpenEJB/TomEE (because you don’t want to loose time ;)).

Here are the standard cases you can need (from the fastest to the slowest but more realistic):

  • embedded container
  • embedded container with webservices features
  • embedded TomEE
  • remote TomEE

Of course TomEE is a great product and has a workaround for such a case. It is even a sample available on openejb source repository: http://svn.apache.org/repos/asf/openejb/trunk/openejb/examples/multiple-arquillian-adapters/

The idea is to be able to activate an adapter through a system property. You can use:

  • embedded
  • tomee-embedded
  • tomee-remote
  • tomee-webapp (well it exists but forget this one, it is likely an internal one to check TomEE webapp)

So you count and say: “what about embedded container with webservices features”? I didn’t forget it but that’s simply an embedded container with some specific configuration.

The “magic” system property is: “openejb.arquillian.adapter” (or “tomee.arquillian.adapter”).

Ok, so we got a way to select an adapter if multiple are available at classpath, now how to select the configuration? Arquilian includes a solution: simply define multiple container configurations with different qualifiers and set “arquillian.launch” system property to the right qualifier. It is the tip we use to remove the remote feature to the embedded case (by default there are enabled if available) when we don’t need them.

Want to see more real stuff?

First let’s add adapters to your pom:

    <!-- common arquillian dependencies -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.jboss.arquillian.junit</groupId>
      <artifactId>arquillian-junit-container</artifactId>
      <version>${arquillian.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- utility test deps -->
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>ziplock</artifactId>
      <version>${tomee.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- additional container part for embedded JAX-RS test -->
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>openejb-cxf-rs</artifactId>
      <version>${openejb.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- arquillian adapters -->
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>arquillian-openejb-embedded-4</artifactId>
      <version>${openejb.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>arquillian-tomee-embedded</artifactId>
      <version>${tomee.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>arquillian-tomee-remote</artifactId>
      <version>${tomee.version}</version>
      <scope>test</scope>
    </dependency>

Add the corresponding configuration in arquillian.xml:

<?xml version="1.0"?>
<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="embedded">
    <configuration>
      <property name="properties">
        # to ensure we don't start remote container even if it is found at classpath
        openejb.embedded.remotable = false
      </property>
    </configuration>
  </container>
  <container qualifier="embedded-remote">
    <configuration>
      <property name="properties">
        # optional if found at classpath
        openejb.embedded.remotable = true
      </property>
    </configuration>
  </container>
  <container qualifier="tomee-embedded">
    <configuration>
      <property name="httpPort">-1</property>
      <property name="stopPort">-1</property>
      <property name="dir">target/apache-tomee-embedded</property>
      <property name="appWorkingDir">target/arquillian-test-working-dir-2</property>
    </configuration>
  </container>
  <container qualifier="tomee-remote">
    <configuration>
      <property name="httpPort">-1</property>
      <property name="stopPort">-1</property>
      <property name="ajpPort">-1</property>
      <property name="dir">target/apache-tomee-remote</property>
      <property name="appWorkingDir">target/arquillian-test-working-dir-2</property>
    </configuration>
  </container>
</arquillian>

And finally configure several surefire executions (one by kind of container) with the right openejb.arquillian.adapter and arquillian.lanuch system properties. To be clean you can define one marking interface by kind of container and mark your tests with a JUnit @Category using the right marking interface (inclusions/exclusions works well too).

In the following surefire config we use @Category:

      <plugin>
        <!--
        Redefining execution to:
        1. set the right arquillian adapter
        2. set the category to execute (include/exclude works too)
        3. set the arquillian launcher to use
        -->
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.12</version>
        <executions>
          <execution>
            <id>test-embedded</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <groups>org.superbiz.embedded.standalone.Embedded</groups>
              <systemPropertyVariables>
                <arquillian.launch>embedded</arquillian.launch>
                <openejb.arquillian.adapter>openejb</openejb.arquillian.adapter>
              </systemPropertyVariables>
            </configuration>
          </execution>
          <execution>
            <id>test-embedded-remote</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <groups>org.superbiz.embedded.remote.EmbeddedRemote</groups>
              <systemPropertyVariables>
                <arquillian.launch>embedded-remote</arquillian.launch>
                <openejb.arquillian.adapter>openejb</openejb.arquillian.adapter>
              </systemPropertyVariables>
            </configuration>
          </execution>
          <execution>
            <id>test-tomee-embedded</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <groups>org.superbiz.tomee.embedded.TomEEEmbedded</groups>
              <systemPropertyVariables>
                <arquillian.launch>tomee-embedded</arquillian.launch>
                <openejb.arquillian.adapter>tomee-embedded</openejb.arquillian.adapter>
              </systemPropertyVariables>
            </configuration>
          </execution>
          <execution>
            <id>test-tomee-remote</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <groups>org.superbiz.tomee.remote.TomEERemote</groups>
              <systemPropertyVariables>
                <arquillian.launch>tomee-remote</arquillian.launch>
                <openejb.arquillian.adapter>tomee-remote</openejb.arquillian.adapter>
              </systemPropertyVariables>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <skip>true</skip>
          <parallel>none</parallel>
          <threadCount>1</threadCount>
        </configuration>
      </plugin>

Here we are, simply annotate @Category(TomEERemote.class) for instance your tests using the tomee remote adapter and it will be executed using the right adapter :).

Note: this feature is currently available on trunk and will be in 1.1.0 release of TomEE (4.1.0 for OpenEJB).

Advertisements

2 thoughts on “Running Arquillian test using different TomEE/OpenEJB adapters in the same build/artifact

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s