How do I add JAR files to the test archive?

A fairly common requirement is to add dependent JAR files to the test archive. There is an open feature request (ARQ-66) to add this capability to Arquilian natively. This FAQ will explain how you can accomplish this requirement in the interim. The instructions are specific to a Maven project, but the concept can be extended for other types of projects as well (Gradle, etc).

 

If your project is using Maven, the testCompile step will resolve any test dependencies and put them in your local Maven repository. By the time the test executes, you can be sure that the JAR files you need will be in your local repository. That allows us to simply reference a file in a central place on the local filesystem to include it into the test archive.

 

Here's a fairly crude resolver that converts a Maven artifact reference into a java.io.File object.

 

import java.io.File;
 
public class ArtifactResolver
{
   private static final String LOCAL_MAVEN_REPO =
         System.getProperty("maven.repo.local") != null ?
               System.getProperty("maven.repo.local") :
               (System.getProperty("user.home") + File.separatorChar +
               ".m2" + File.separatorChar + "repository");
 
   public static File resolve(String groupId, String artifactId, String version)
   {
      return new File(LOCAL_MAVEN_REPO + File.separatorChar +
            groupId.replace(".", File.separator) + File.separatorChar +
            artifactId + File.separatorChar +
            version + File.separatorChar +
            artifactId + "-" + version + ".jar");
   }
 
   public static File resolve(String qualifiedArtifactId)
   {
      String[] segments = qualifiedArtifactId.split(":");
      return resolve(segments[0], segments[1], segments[2]);
   }
}

 

If you are using an alternative location for your local Maven repository, controlled using the maven.repo.local Maven property, you will need to promote that property as a Java system property in the surefire plugin configuration:

 

<plugin>       
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.4.3</version>
   <configuration>
      <systemProperties>
         <property>
            <name>maven.repo.local</name>
            <value>${maven.repo.local}</value>
         </property>
      </systemProperties>
   </configuration>
</plugin>

 

Otherwise, the default location will be used.

 

You'll now add the required JAR files into your archive in the Arquillian @Deployment method. Let's assume that we need to add commons-logging and commons-lang.

 

When you need to add a JAR file to your artifact, you should use an artifact that is a library container, such as a WAR or an EAR (though you could also use Archive#merge() to dump the classes into a JavaArchive). In this case, we'll choose a WAR. Notice that I've added the beans.xml to the WEB-INF directory, which is required if I want to use CDI in a WAR deployment.

 

 

@Deployment
public static Archive<?> createTestArchive()
{
   WebArchive war = ShrinkWrap.create("test.war", WebArchive.class)
         .addClasses(...)
         .addLibraries(
               ArtifactResolver.resolve("commons-logging:commons-logging:1.1.1"),
               ArtifactResolver.resolve("commons-lang:commons-lang:2.5"))
         .addWebResource(new ByteArrayAsset(new byte[0]), "beans.xml");
   // verify that the JAR files ended up in the WAR
   System.out.println(war.toString(true));
   return war;
}

 

 

Obviously, it would be nice to use the version of the artifact defined in the dependencyManagement section of the POM file. It might also be convenient to declare these dependencies using annotations on the @Deployment method for simple cases. We welcome your ideas.