Posts Tagged ‘aspectj-maven-plugin’

JUnit test Struts applications with mock objects and Maven

november 28, 2009

Let me start by giving credits to Walter Jia who wrote the article Unit test Struts applications with mock objects and AOP. This was a great article which pushed me in the right direction. I wanted to use Maven instead of Ant, which meant I had to configure a pom.xml. There are a few details which you need to know to migrate to Maven. I wanted to stay close to the original example, so I didn’t upgrade EasyMock and JUnit yet.

Project layout

Below is the project structure based on the standard directory layout described by Maven. The aspect-folder is defined by the aspectj-maven-plugin. You could put the .aj-file inside the src/test/java, but this way you keep the files in their own folder.
The org.acme.StrutsActionPreExecuteListener is a helperfile, but it’s java so I’ve put it in the src/test/java folder.

  • StrutsTest2
    • src/main/java
      • com.foo.bar.ActionService
      • com.foo.bar.SimpleAction
    • src/main/webapp
      • WEB-INF
        • struts-config.xml
        • web.xml
    • src/test/aspect
      • org/acme/StrutsActionPreExecuteNotifier.aj
    • src/test/java
      • com.foo.bar.SimpleActionTest
      • org.acme.StrutsActionPreExecuteListener
    • pom.xml

The Pom.xml

I hope you’ll all understand the dependency-section, so I’ll just focus on the build-section.
First of all, the MockStrutsTestcase expects a WEB-INF/web.xml and a WEB-INF/struts-config.xml on the classpath. I want to make use of the files which will be deployed with the war as well. So I’ve defined these two files as testResources. If you want to use a specific test-version, you have to make these files inside src/test/resources/WEB-INF and they’ll be picked by Maven by default.

<testResources>
    <testResource>
        <directory>src/main/webapp</directory>
        <includes>
            <include>WEB-INF/*.xml</include>
        </includes>
    </testResource>
</testResources>

I already mentioned the aspectj-maven-plugin, which we need to include as well. It’s pretty straight-forward. Include the plugin and add an execution-section. Defining the plugin goals (in our case only test-compile) is enough. This goal is bound to the process-test-sources phase of Maven, so there’s no need to specify a phase inside the exection-section.

<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>aspectj-maven-plugin</artifactId>
 <version>1.2</version>
 <executions>
  <execution>
   <goals>
    <goal>test-compile</goal>
   </goals>
  </execution>
 </executions>
</plugin>

It looks like we’re done. But if we run the tests, both tests will fail because of a NullPointerException. The service isn’t injected, which means the preActionExecuteOccured method isn’t called.
So here’s the pitfall. It’s not (only) the test class which has to be compiled with AspectJ, especially the Action class needs to be compiled like this as well, but only for testing! So we have to tell Maven to use these files too. This is done by configuring the aspectj-maven-plugin.
Add to the execution-section the following lines:

<configuration>
  <weaveMainSourceFolder>true</weaveMainSourceFolder>
</configuration>

This way the Action is added to the test classes and will be compiled by the aspectj-maven-plugin. Note that this Action is not the one that will be packaged, since Maven uses seperate folders for main classes and test classes.
You might want to finetune this, because now all (re)source files on the main path will be added to the test classpath, so some fileoverwriting might occur.

The complete build-section will look like this:

<build>
  <testResources>
    <testResource>
      <directory>src/main/webapp</directory>
      <includes>
        <include>WEB-INF/*.xml</include>
      </includes>
    </testResource>
  </testResources>
 <plugins>
  <plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>aspectj-maven-plugin</artifactId>
   <version>1.2</version>
   <executions>
    <execution>
     <goals>
      <goal>test-compile</goal>  <!– use this goal to weave all your test classes –>
     </goals>
     <configuration>
       <weaveMainSourceFolder>true</weaveMainSourceFolder>
     </configuration>
    </execution>
   </executions>
  </plugin>
 </plugins>
</build>

The Strutstest2.zip can be downloaded from Box.net

Advertenties