Enterprise Java

Java EE7 and Maven project for newbies – part 5 – Unit testing using Arquillian / Wildfly 8

Resuming from the previous parts

Part #1, Part #2, Part #3, Part #4,
This is the first ‘extra’ post, based on the  maven JavaEE7 demo project I am ‘building’ on this series of blog posts. We have already defined a solid structure and some modules. One very common case in an application like this, is to use Arquillian (+JUnit), a god sent framework, that enable us to unit test our EJB services using a ‘real’ application server, most probably the same that we are going to deploy to. I am actually following the basic setup guide as it can be found here, the difference is that I am going to setup Wildfly 8.1 as my embedded container to host my unit tests.
Widlfy 8.1 is a fully blown JavvaEE7 container, so I can safely test all my features.

Arquillian mind set and Maven

One of the basic things you need to understand in order to adopt Arquillian in your Maven-ized project is the following  terms (ideas) that are actually implemented as dependencies.

  • You need the Arquillian framework/library of course, imagine that it is a new car but is missing it’s engine. The front part it’s empty.
  • You need an Arquillian Container Adapter, imagine that you need to install some kind of placeholders in the front part of your car, something like a frame that is going to be used so that an engine can be ‘installed’.
  • You need a real container (application server), this is the engine that we are going to fit into our car.
  • You need JUnit, this is the ‘test track‘ that your car is going to run and be tested.
  • You need your code (your EJB(s)), these are the passengers that are going to be placed in the car and test a ride on the Junit track.

Defining the dependencies on the parent pom

As we have already elaborated in the previous 4 posts, the parent pom is the place to define the dependencies and their versions of libraries to be used in our application.  Have in mind the above list of terms let’s get started and update the dependencyManagement section  of our parent pom.

	

     <junit-version>4.11</junit-version>
     <arquillian-version>1.1.4.Final</arquillian-version>
     <arquillian-wildfly-version>8.1.0.CR2</arquillian-wildfly-version>
     <arquillian-transaction-version>1.0.1.Final</arquillian-transaction-version>
    </properties>
     <dependencyManagement>
          <dependencies>
              <dependency>
                  <groupId>javax</groupId>
                  <artifactId>javaee-api</artifactId>
                  <version>${javaee-api-version}</version>
              </dependency>
              <!-- -JUNIT-->
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>${junit-version}</version>
              </dependency>
              <!-- rquillian itself-->
              <dependency>
                  <groupId>org.jboss.arquillian</groupId>
                  <artifactId>arquillian-bom</artifactId>
                  <version>${arquillian-version}</version>
                  <scope>import</scope>
                  <type>pom</type>
              </dependency>
              <!-- this is in an extention to arquillian it is optional-->
              <dependency>
                  <groupId>org.jboss.arquillian.extension</groupId>
                  <artifactId>arquillian-transaction-bom</artifactId>
                  <version>${arquillian-transaction-version}</version>
                  <type>pom</type>
                  <scope>import</scope>
               </dependency>
               <!-- this is container adapter for wildfly-->
                <dependency>
                   <groupId>org.wildfly</groupId>
                   <artifactId>wildfly-arquillian-container-embedded</artifactId>
                   <version>${arquillian-wildfly-version}</version>
                </dependency>
                <!-- this is the wildfly emb.container - BUT eventually it is not a fully blown emb.container-->
                <dependency>
                   <groupId>org.wildfly</groupId>
                   <artifactId>wildfly-embedded</artifactId>
                   <version>${arquillian-wildfly-version}</version>
               </dependency>
           </dependencies>
     </dependencyManagement>

Some tips on the above fragment:

  • Some of the dependencies are of type pom, and scope import. This is actually a special case on defining group of dependencies all together. A pom type dependency, means that this is a group of individual libraries grouped together under this definition. You only need to define this uber pom  and you will inherit the individual dependencies within it. In the Maven terminology this grouping of dependencies are called ‘BOM‘ or also known as Bill of Materials. Arquillian is consisted of several concrete libraries and dependencies, instead of defining each one of the, one by one, we have the same result if we define the arquillian-bom.
  • The ‘arquillian-transaction-bom‘ is an optional dependency, you may not define it, it adds extra features to the arquillian engine and in your tests. One of the most famous ‘extra’ features is the ‘@Transactional’ arquillian annotation. See details here or here.
  • A special case, for Wildfly and JBoss. You will notice the dependency, ‘wildfly-embedded‘, you will assume that this is a ‘embedded‘ uber jar version of the Wildfly application server, like the one for Glassfish. Eventually this is not, and this is a common mistake that people make when trying to setup Arquillian with Wildfly. In order to make the whole thing work you need to download the ‘real’ application server. Have a look on the following section, where will will tackle this special case.

Configuring our ejb module for Arquillian and tests

In our demo applications we have ‘coded’ most of our EJB services on the module called sample-ejb. So we need to add extra configuration to it’s pom in order to ‘fire‘  junit+arquillian tests during the test phase of this module.

Most of the configuration will do on this pom, is to cover this ‘special‘ case of Widlfly not being offered as a fully blown embedded container. So in order to make the whole mechanism work we need, to tell Maven, during our test phase, to download the Wildfly.zip (as we would do using a browser for example) unzip it somewhere, and the point Arquillian to the path. Once that is done, rAquillian will take over.

Downloading the wildfly server, before hand

The configuration below is written in the sample-services pom, our ‘EJB services’ module:

     <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
                  <execution>
                     <id>unpack</id>
                         <phase>process-test-classes</phase>
                          <goals>
                              <goal>unpack</goal>
                           </goals>
                     <configuration>
                     <artifactItems>
                         <artifactItem>
                            <groupId>org.wildfly</groupId>
                            <artifactId>wildfly-dist</artifactId>
                             <version>8.1.0.Final</version>
                             <type>zip</type>
                             <overWrite>false</overWrite>
                             <outputDirectory>target</outputDirectory>
                         </artifactItem>
                     </artifactItems>
                  </configuration>
               </execution>
           </executions>
      </plugin>

Some tips on the above fragment:

  • We use the maven-dependency-plugin
  • We instruct the plugin to kick in during the ‘process-test-classes’ phase of the Maven lifecycle, and when it kicks in to execute the ‘unpack’ goal. So before Maven starts running the tests the above part of the configuration will have downloaded and unpacked Wildfly 8.1 to the class path.

 Running the tests, using maven – surfire plugin

Again the code below is part of the sample-services.pom. We actually configure Maven Surefire Plugin, which is the plugin that executes the Junit-Arquilian tests.

    <plugin>
         <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <!-- Fork every test because it will launch a separate AS instance -->
             <forkMode>always</forkMode>
             <systemPropertyVariables>
                <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                <jboss.home>${project.basedir}/target/wildfly-8.1.0.Final</jboss.home>
               <module.path>${project.basedir}/target/wildfly-8.1.0.Final/modules</module.path>
              </systemPropertyVariables>
              <redirectTestOutputToFile>false</redirectTestOutputToFile>
         /configuration>
     </plugin>

Some tips on the above fragment:

  • Surefire provides the execution environment for the unit tests. In our case we have Junit-Arquillian powered tests. In order Arquillian to correctly initialize itself and to identify the container we need to pass as system parameters, the path of the download application server. Remember that wildfly / jboss is a special case.  The container will already be downloaded on out /target folder.

Add the required dependencies on the sample-services module

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.wildfly</groupId>
            <artifactId>wildfly-arquillian-container-embedded</artifactId>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.wildfly</groupId>
            <artifactId>wildfly-embedded</artifactId>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-transaction-jta</artifactId>
            <scope>test</scope>
        </dependency>

 Create a sample Test

      package gr.javapapo;
     
    import org.jboss.arquillian.container.test.api.Deployment;
    import org.jboss.arquillian.junit.Arquillian;
    import org.jboss.shrinkwrap.api.ShrinkWrap;
    import org.jboss.shrinkwrap.api.asset.EmptyAsset;
    import org.jboss.shrinkwrap.api.spec.JavaArchive;
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
     
    import javax.ejb.EJB;
     
    /**
     * Created by papo on 5/31/14.
     */
    @RunWith(Arquillian.class)
    public class DemoArquillianTest {
     
        @EJB
        UserServices dummyService;
     
        @Deployment
        public static JavaArchive createDeployment() {
            return ShrinkWrap.create(JavaArchive.class)
                    .addClass(UserServices.class)
                    .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
        }
     
        @Test
        public void testSaysHello() {
            Assert.assertEquals("hello",dummyService.sayHello());
        }
    }

We are done

Under the sample-parent folder level, type:

mvn clean package

Paris Apostolopoulos

Paris is a senior software engineer focusing on J2EE development, loves Business process modelling and is keen on software quality challenges. He is passionate about Java and Java communities. He is a co-founder and administrator of the first Java User Group in greece(JHUG.gr) and occasional speaker on meet-ups and seminars and regular blogger. For his contributions and involvement on the Java community he has been awarded the title of Java Champion in 2007 by Sun Microsystems.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Kapil
Kapil
9 years ago

Hi,

Thanks for the tutorial.

How can I add resources (eg. persistence.xml) from dependent modules in the createDeployment method.

Regards,
Kapil

javapapo
9 years ago

Take a look on part6 of this tutorial
http://javapapo.blogspot.gr/2014/06/java-ee7-and-maven-project-for-newbies_23.html

Where I add resources. (e.g a test-persistence.xml)

:)

Edmond
Edmond
9 years ago

I have done exactly as it stands it this tutorial. Though when i run “mvn clean package” I get the following error:

Failed to process phase INSTALL of deployment “test.war”

Caused by: java.util.ServiceConfigurationError: javax.servlet.ServletContainerInitializer: Provider com.sun.xml.ws.transport.http.servlet.WSServletContainerInitializer not found

What am I missing?

Regards
Edmond

javapapo
9 years ago

Have you bundling extra jars apart from those defined in the example? JAX-WS ?

Alexandr
Alexandr
8 years ago

I’m getting guava library in my code, when try to start test, I get:
ERROR [org.jboss.msc.service.fail] MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./skinning: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./skinning: Failed to start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_45]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_45]
Caused by: java.lang.NoClassDefFoundError: com/google/common/collect/Sets

Is there a way to add guava as wildfly module via maven configuration? Is there any solution?

Jeeva
Jeeva
8 years ago

how to configure the pom.xml to make arquillium to start wildfly instance with “standalone-full.xml”

Back to top button