javagradlejboss-arquillianshrinkwrap

Difficulty adding package to Shrinkwrap archive in Arquillian test


I'm trying to add the package org.jibble.pircbot to my test archive using shrinkwrap. I've tried every variation I can think of, but in all cases the package is not found. However, for some reason, the classes can be added individually, but any anonymous inner classes are not added.

  @Deployment
  public static WebArchive createDeployment() {
    return ShrinkWrap.create(WebArchive.class, "RcCustomerTest.war")
//      .addPackages(true, PircBot.class.getPackage())
//      .addPackages(true, "org.jibble.pircbot")
      .addClasses(PircBot.class,
        ReplyConstants.class,
        IrcException.class,
        NickAlreadyInUseException.class,
        InputThread.class,
        OutputThread.class,
        Queue.class)
      .addClass(DccManager.class) // Inner classes not added!
      .addPackages(true, "com.recursiveloop.webcommon")
      .addPackages(true, "com.recursiveloop.jloop.core.irc")
      .addAsResource("config.properties")
      .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
      .addAsWebInfResource("jboss-web.xml", "jboss-web.xml")
      .addAsWebInfResource("jboss-deployment-structure.xml", "jboss-deployment-structure.xml")
      .addAsResource("persistence.xml", "META-INF/persistence.xml")
      .setWebXML("web.xml");
  }

This results in the exception

...
Caused by: java.lang.NoClassDefFoundError: org/jibble/pircbot/DccManager$1
        at org.jibble.pircbot.PircBot.<init>(PircBot.java:3081)
        ...

This is odd because browsing the shrinkwrap source code I found a function that makes the following assertion

Assert.assertTrue("Adding a class should also add the anonymous inner classes",
    getArchive().contains(expectedPathAnonymousInnerClass));

But sadly, it seems that no test cases actually call this function.

However, the question remains - why isn't shrinkwrap finding the package when I call addPackages(true, "org.jibble.pircbot")? I look at the resulting archive and there's no sign of org.jibble.pircbot, and obviously there are the inevitable ClassDefNotFound exceptions:

...
Caused by: java.lang.NoClassDefFoundError: Failed to link com/recursiveloop/jloop/core/irc/VisitorConnection (Module "deployment.RcCustomerTest.war:main" from Service Module Loader): org/jibble/pircbot/PircBot
...

I'm using gradle, but if I was using maven, the maven resolver would probably do the job. There's a gradle resolver, but it doesn't quite do the same thing. My best attempt at using it was as follows

return ShrinkWrap.create(EmbeddedGradleImporter.class)
      .forProjectDirectory()
      .forTasks("integTestWar")
      .importBuildOutput("build/libs/integTest.war").as(WebArchive.class);

This kicks off a gradle task and inserts the test classes into the resulting archive. The challenge was getting gradle to build a correct war file. I wanted it to contain the resource files (deployment descriptor's etc.) belonging to the integration test sourceset, not the main sourceset, but I just couldn't get it to work.

FYI I'm using shrinkwrap version 1.2.3, which is the latest.

Any help would be much appreciated.


Solution

  • I solved it by using the maven resolver as follows:

    return ShrinkWrap.create(WebArchive.class, "RcCustomerTest.war")
      .addAsLibraries(Maven.resolver()
        .loadPomFromFile("build/pom.xml")
        .resolve("pircbot:pircbot")
        .withTransitivity().asFile())
    
        ...
    

    The POM file is generated using gradle's eclipse plugin, like so

    task writeNewPom << {
      pom {
        writeTo("$buildDir/pom.xml")
      }
    }
    

    which is set to run before the integration test.

    It turns out that the maven resolver can be used without a POM, but you'd have to specify the artifact in the test and make sure it remains up-to-date with what your project uses. Integration tests are already a pain to maintain, so it's better to resolve the dependency from the POM so you know that it's the right version (one less thing to worry about).