alt
January 12th, 2011

by Ivan St. Ivanov

This is the last blog post in the three-part series on unit testing services managed by the most popular types of containers in the Java world. In the first part I showed you how you can use Spring’s dependency injection container together with Spring test framework to easily inject your services into the unit tests. In the second part we took a look at the Glassfish embedded container, which we started in our test and then looked up the service under test from there. Java EE 6′s embedded server feature is really a big leap forward, but it has a slight problem. As the test code is running outside of the container, the managed objects (such as EJBs) cannot be injected, so in the tests you cannot take advantage of the new features brought by the CDI specification. You should lookup your EJB from the JNDI context, which even though well specified, is still a little bit clumsy.

The Arquillian library from JBoss solves this problem by providing the opportunity to programmatically create and deploy archives on any kind of embedded server (JBoss, Glassfish, Jetty). In the same time you can declare the dependency of your test to the server-managed objects and you don’t have to look them up any more in the JNDI context.

The use case is the same as in the first two posts. We are developing football statistics program, one aspect of which is working with teams. Our sample service that we want to test has two methods: one for creating a team and another one for looking up all the teams coming from a certain country. The team is a JPA entity, which is stored in the database through the entity manager. Here is again the diagram:

Same common stuff

The project setup right to the test is the same as in the previous part:

Create the project and add the needed dependencies:

mvn archetype:create -DgroupId=com.foo -DartifactId=my-bar-javaee -DarchetypeArtifactId=maven-archetype-webapp
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <inherited>true</inherited>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>
  </plugins>
</build>

Take also the good old JPA entity from the first two parts of this series:

@Entity
@NamedQuery(name = "findAllTeamsByCountry", query = "select t from Team t where t.country = :country")
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String city;
    private String stadium;
    private String country;
...
// Getters and setters skipped for clarity
}

The persistence XML is the same as in the Embedded Glassfish example. We use again JTA data source. The only difference is that I have changed the default data source name (jdbc/__default) to a custom one (jdbc/foo) just to see how this works:

<?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="barPU">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/foo</jta-data-source>
    <class>com.foo.Team</class>
    <properties>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
      <property name="eclipselink.logging.level" value="INFO" />
    </properties>
  </persistence-unit>
</persistence>

Our session bean is (surprise!) exactly the same as in the previous part:

@Stateless
public class TeamEjb {

    @PersistenceContext(unitName = "barPU")
    private EntityManager em;

    public Team createTeam(Team team) {
        em.persist(team);
        return team;
    }

    @SuppressWarnings("unchecked")
    public List<Team> findAllTeamsFromCountry(String country) {
        Query query = em.createNamedQuery("findAllTeamsByCountry");
        query.setParameter("country", country);
        return query.getResultList();
    }
}

And we need to configure in our pom.xml the EJB jar dependency together with the repository that contains it:

<dependency>
  <groupId>org.glassfish</groupId>
  <artifactId>javax.ejb</artifactId>
  <version>3.0</version>
  <scope>provided</scope>
</dependency>
<repositories>
 <repository>
   <id>Glassfish</id>
   <name>Glassfish Repository</name>
   <url>http://download.java.net/maven/glassfish</url>
 </repository>
</repositories>

Writing Arquillian tests

We finally came to the stage when we go into the new stuff for this last part of the series.

What is so particular about Arquillian that makes it so different than the standard testing frameworks? Well, it does for us the starting of the container and deploying the classes under test. And by the container I mean any container (well, here’s the list of the supported ones) and not just a special one. The first thing you have to do before writing your first test is to make sure that you provide the Arquillian API dependency in your pom XML:

<dependency>
  <groupId>org.jboss.arquillian</groupId>
  <artifactId>arquillian-junit</artifactId>
  <version>1.0.0.Alpha4</version>
  <scope>test</scope>
</dependency>

This and most of the Arquillian libraries are available on the JBoss maven repository, so you need to make sure that it is also referenced either in the pom.xml or in your settings.xml:

<repository>
  <id>JBoss</id>
  <name>JBoss Repository</name>
  <url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>

Having this available, we may proceed to writing the test. The first thing to notice here is that in order to take advantage of Arquillian’s features, you need to annotate your test so that it is run with the Arquillian test runner and not the default one. Remember, the same thing you did when creating your spring framework based test? Here is how you do it:

import org.jboss.arquillian.junit.Arquillian;

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

The next thing that we need to do is to create the archive that we want to deploy in the container. Basically it should contain all the classes that we are about to test. This is done in Java code, not in a fancy XML configuration. The method which contains the code should be annotated with @org.jboss.arquillian.api.Deployment. It returns an org.jboss.shrinkwrap.api.Archive object. This archive can be java archive (a jar), web archive (war), etc. It is created by the ShrinkWrap API, which represents kind of a fluent interface. It can be instructed what kind of archive you want to create, what classes and even resources to pack inside. Here is how it can be put to work:

@Deployment
public static Archive<?> createDeployment() {
    return ShrinkWrap.create(JavaArchive.class, "foo.jar")
        .addClasses(Team.class, TeamEjb.class)
        .addManifestResource("META-INF/persistence.xml", ArchivePaths.create("persistence.xml"));
}

Now we can continue with our test:

@EJB
private TeamEjb teamEjb;

@Test
public void testTeamService() throws NamingException {
    Team testTeam = new Team();
    testTeam.setName("CSKA");
    testTeam.setCity("Sofia");
    testTeam.setCountry("Bulgaria");
    testTeam.setStadium("Bulgarska armiya");

    teamEjb.createTeam(testTeam);

    assertEquals(1, teamEjb.findAllTeamsFromCountry("Bulgaria").size());
}

The test method is the same as in the Embedded Glassfish example with the slight difference that there is no need to look up the TeamEjb. On the other hand you can see that it is injected for us by Arquillian using the good old @EJB annotation.

And this is it. Besides the fact that we don’t have to worry about JNDI and looking up our test beans any more, we don’t have to care about starting and stopping the container either. Arquillian does it all for us. Speaking about the container, we’ll need to configure it somehow.

Configuring the Arquillian container

Arquillian itself is just a library. In order for it to work, you need to configure a Java EE container with it. The good news is that it supports plenty of them – both embedded and remote ones. Here is the full list. You can see the big variety – Java EE 5, Java EE 6, Servlet, CDI, EJB. While preparing the sample code for this article, I wanted to use the embedded JBoss implementation. However, after maven downloaded the whole internet, my test failed. It appeared that Arquillian was still looking for remote JBoss, not the embedded one. However, I tried this in the beginning of November last year (shame on me that it took me two months to publish this). So maybe if you give it a try today, you will be more successful.

So I decided to go back to Embedded Glassfish. In order to configure a container with Arquillian you need to do a couple of things:

1) Get the respective Arquillian container dependencies. In maven it looks like this:

<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3</artifactId>
<version>1.0.0.Alpha4</version>
<scope>test</scope>
</dependency>
<dependency>
  <groupId>org.glassfish.extras</groupId>
  <artifactId>glassfish-embedded-all</artifactId>
  <version>3.0</version>
  <scope>test</scope>
</dependency>

2) Tell Arquillian which container you are using and some information about it. It is done with the help of arquillian.xml. Its usual place is in the src/test/resources directory:

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/arquillian"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:glassfish="urn:arq:org.jboss.arquillian.container.glassfish.embedded_3">
  <glassfish:container>
    <glassfish:instanceRoot>src/test/resources/glassfish</glassfish:instanceRoot>
    <glassfish:bindPort>9090</glassfish:bindPort>
    <glassfish:autoDelete>false</glassfish:autoDelete>
  </glassfish:container>
</arquillian>

Basically you tell Arquillian which container you choose by declaring one of the available XML namespaces (line 4). Then the container specific configuration follows. In our sample case we have Embedded Glassfish, so we need to tell the test library where to find the server configuration (line 6). We specified here src/test/resources/glassfish, which means that we’ll have to copy there the Glassfish domain in nearly the same way we did in the previous part of the series.

The list of all the container’s namespaces and configurations can be found on this page.

Configuring the server

As mentioned above, you will still have to provide a domain.xml file under your resources directory. You can take this from an existing Glassfish installation, clear it from some needless stuff (deployed applications for example) and place it in the test/resources directory. The exact place is specified in Arquillian’s XML in the instanceRoot tag. It basically points to Glassfish’s root directory. Of course you should provide just the domain.xml inside. And its location is not the usual one (<root>/domains/domain1/config), but straight under <root>/config. It is a good idea to get this file from a clean installation, because this guarantees that you will need to remove less stuff.

What you need to add for sure there is the database connectivity information required by JPA. First declare the JDBC resource

<jdbc-resource pool-name="HsqldbPool" jndi-name="jdbc/foo" object-type="user" enabled="true"/>

You maybe noticed that the jndi-name attribute matches the content jta-data-source tag of the persistence XML.

And then configure the JDBC connection behind the above pool:

<jdbc-connection-pool is-isolation-level-guaranteed="false" name="HsqldbPool" driver-classname="org.hsqldb.jdbcDriver" res-type="java.sql.Driver">
  <property value="9001" name="PortNumber" />
  <property value="" name="Password" />
  <property value="sa" name="User" />
  <property value="localhost" name="serverName" />
  <property value="jdbc:hsqldb:mem:foobar" name="URL" />
</jdbc-connection-pool>

The last thing that remained before running the test for the first time is to add the HSQL DB dependency in our pom.xml:

<dependency>
  <groupId>org.hsqldb</groupId>
  <artifactId>hsqldb</artifactId>
  <version>2.0.0</version>
  <scope>test</scope>
</dependency>

With everything in place, you can finally go on and start the test!

Conclusion

This was the third and final part of our series on testing services running in the most popular containers in the Java world. Today you found out how easy it is to use the Arquillian library so that you can avoid explicit start of a container, then looking up your service from there, testing it and stopping the container. You saw how to create the test archive programmatically using the ShrinkWrap API. Then I described how to configure Arquillian with the different containers.

This is it for now on unit testing containers. I hope that this series was helpful to you. Stay tuned on nosoftskills.com for other [Java] technology articles.

Resources

You can download the same code from here.

One Response to “ Unit testing services, part 3 – Arquillian ”

  1. Carlos says:

    Thank you for the three parts very interesting

Leave a Reply


− six = 1