Continuous code re-factoring – part-2 Unit Testing on the container, the Arquillian way


arquillian_logo_450px

The Problem:

JUnit is probably one of the Top 5 Java open source tool developed by Java community. Until the IOC and Dependency Injection comes in to picture it is all well. But the moment containers taken care of injecting objects for you, the product development became lot easier. Now the programmers just need to describe how the Object should get created, your container will take care of injecting your Object. But on the downside, it makes the unit testing lot harder. To unit test your methods, one need to mock all the Objects that are needed to test a particular method. One of the most common Object is your EntityManager. It is the whole lot of  time-consuming effort to mock all the Objects to do your Unit Testing that will eventually consume your development time. Developers tend to move away from writing unit test cases, which will affect the code coverage. The lesser the code coverage, higher the code breaks. So your continuous code re-factor is in huge risk.

The saviour – Arquillian:

Arquillian is an open source test framework from JBoss.  It integrate with JUnit and make your existing test cases to run on Arquillian container. The way Arquillian works is instead of mock the dependent Objects, Describe what are the Objects are dependent to unit test your class. Arquillian bundle the dependent classes and create a WAR and deploy in to the JBoss server and runs the unit test on your actual JBoss server.

The Advantage :

1. Developers no need to mock the Objects.

2. We are actually testing container injected Objects, just like your code will run after you deploy the WAR file.

3. Since only required classes been getting deployed, you are not deploying the entire WAR file. So the testing is faster.

4. It takes the pain out from the developers and increase the development time.

The Hello World:

Lets see how we can run a simple Hello World test case that will inject the Entity Manager. I’m taking the Entity Manager as an example because it is a common use case and I found very less resource on the web as well.

Step 1:

Configure your JBoss Home on your environment variable.

JBOSS_HOME = “<jboss home directory>

Step 2:

Maven dependency configuration


<properties> <version.shrinkwrap.resolvers>2.0.0-beta-5 </version.shrinkwrap.resolvers> </properties>


<dependency>

<groupId>org.jboss.as</groupId>
 <artifactId>jboss-as-arquillian-container-managed</artifactId>
 <version>7.1.1.Final</version>
 <scope>test</scope>
 <exclusions>
 <exclusion>
 <artifactId>org.apache.felix.resolver</artifactId>
 <groupId>org.apache.felix</groupId>
 </exclusion>
 </exclusions>
 </dependency>

<dependency>
 <groupId>org.apache.felix</groupId>
 <artifactId>org.apache.felix.resolver</artifactId>
 <version>1.0.0</version>
 </dependency>
 <dependency>
 org.jboss.arquillian.protocol
 <artifactId>arquillian-protocol-servlet</artifactId>
 <version>1.0.4.Final</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.arquillian.junit</groupId>
 <artifactId>arquillian-junit-container</artifactId>
 <version>1.0.4.Final</version>
 <scope>test</scope>
 </dependency>

<dependency>
 <groupId>org.jboss.spec</groupId>
 <artifactId>jboss-javaee-web-6.0</artifactId>
 <version>3.0.2.Final</version>
 <type>pom</type>
 <scope>provided</scope>
 <exclusions>
 <exclusion>
 <groupId>xalan</groupId>
 <artifactId>xalan</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-api</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-spi</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-api-maven</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-spi-maven</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.shrinkwrap.resolver</groupId>
 <artifactId>shrinkwrap-resolver-impl-maven-archive</artifactId>
 <version>${version.shrinkwrap.resolvers}</version>
 <scope>test</scope>
 </dependency>

<dependency>
 <groupId>xml-apis</groupId>
 <artifactId>xml-apis</artifactId>
 <version>1.4.01</version>
 </dependency>

<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.21</version>
 </dependency>

Step 3:

On your src/test/resources, create a XML file arquillian.xml

</pre>
<?xml version="1.0" encoding="UTF-8"?>
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">

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

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

 <container qualifier="jboss">
 <protocol type="jmx-as7">
 <property name="executionType">REMOTE</property>
 </protocol>
 </container>
</arquillian>
<pre>

Step 4:
On your src/test/resources/META-INF create a file test-persistance.xml like,


</pre>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">

<persistence-unit name="stats-demo" transaction-type="JTA">
 <provider>org.hibernate.ejb.HibernatePersistence</provider>
 [Your JTA Data source configured in standalone.xml | domain.xml]
 <properties>
 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
 <property name="hibernate.show_sql" value="true" />
 <property name="hibernate.format_sql" value="true"/>
 <property name="use_sql_comments" value="true"/>
 <property name="hibernate.connection.provider_class"
 value="org.hibernate.connection.DatasourceConnectionProvider" />
 <property name="transaction.factory_class"
 value="org.hibernate.transaction.JTATransactionFactory" />
 <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
 </properties>
 </persistence-unit>

</persistence>
<pre>

Step 5:
We have completed all the XML configuration to start with Arquillian. Now the JUnit class to test is,

</pre>
package com.ananth.learning.unittest.arquillian;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;

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.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* @RunWith make sure the test case running as a Arquillian test case
*/

@RunWith(Arquillian.class)
public class HelloWorld {

 @Deployment
 public static Archive<!--?--> createDeployment() {
 // Add this if you want to add any lib that been mentioned as a dependency in your maven configuration (pom.xml)
 File[] libs = Maven.resolver().loadPomFromFile("pom.xml")
 .resolve(getDependencyLibs()).withTransitivity().asFile();

 //System.out.println(libs);

 /** Add dependent classes and libs in to Web Archive.
 * please check the API lib, you can addClass() to add single class
 * addClasses() and addPackage(), addPackages() also works work you.
 * Note: you don't need to have beans.xml. It will be created by JBoss by itself.
 */
 WebArchive jar = ShrinkWrap
 .create(WebArchive.class, "test.war")
 .addClass(HelloWorld.class)
 .addAsLibraries(libs)
 .addAsResource("META-INF/test-persistence.xml",
 "META-INF/persistence.xml")
 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");

//System.out.println(jar.toString(true));

return jar;
 }
 // let the container inject for you
 @Inject
 private EntityManager em;

 /**
 * Your actual test case
 */
 @Test
 public void testHello() {
 System.out.println(em.toString());

 }

/**
 * list of dependency module from pom.xml that you may need. (e-g) your common module or persistance module
 */

private static List getDependencyLibs() {
 List<String> list = new ArrayList<>();
 list.add("mysql:mysql-connector-java");
 return list;
 }

}
<pre>

Now all you need to do run the test case just like how you run your normal JUnit test. You can see the WAR getting generated and unit test run on your JBoss Server.!!!

Advertisements

3 thoughts on “Continuous code re-factoring – part-2 Unit Testing on the container, the Arquillian way

Leave a Reply

Please log in using one of these methods to post your comment:

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