Lombok, AspectJ and JUnit

Posted on Posted in Aspect oriented programming

A couple of posts ago I mentioned the incompatibility between Lombok and the AspectJ Eclipse plugin. Of course, JUnit tests also suffer from the incompatibility. Today I’ve been looking for a solution to that problem.

The incompatibility is caused by both AspectJ and Lombok extending the Java editor at the same time and in the same way, so there is little hope this bug is going away soon. I suspect both plugins use the same Eclipse extension point, and the corresponding classes are derived from the same JDT’s base classes. No matter what the reason is, you have to choose either AspectJ or Lombok, and my team chose Lombok.

We avoided the trouble by simply not installing AspectJ. Liferay requires us to use a build script anyway, and we simply included a few lines calling the ant task to weave the aspects. Eclipse doesn’t know about our aspects, and it doesn’t have to: we use it as an editor and a debugger, not as a compiler.

However, if we start the JUnit test cases inside Eclipse using the menu command Run as -> JUnit Test, our avoidance strategy fails. The tests only know the classes generated by Eclipse. But that’s the wrong version, the version without the woven aspects. Our application relies heavily on the aspects, so there’s no way to get the bar green! Most tests will crash immediately.

Currently, three solutions crossed my mind:

  • We could look for a project builder that weaves the aspects when Eclipse compiles the code. We could even write one ourselves (that doesn’t seem to be too difficult, as you can read here or here).
  • We could run the class JUnitCore directly and pass it the fully qualified name of the JUnit test case class. If you are willing to write a few lines of code, you can add the automatic detection of every test case and a window showing the green or red bar.
  • You do without the green bar and use a dedicated build script to run your tests.

We decided to use the build script because we have got a lot of experience writing build scripts. A simple build script running every test case in the directory “JUnitTests” looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="default">
    <target name="default" description="description">
    	<junit showoutput="true" haltonfailure="false" haltonerror="false"
    	       fork="true"
    	       failureproperty="tests.failed"
    	       errorproperty="tests.failed">
    	    <batchtest todir="testresults">
    	        <fileset dir="JUnitTests">
    	            <include name="**/*Test.java"/>
    	        </fileset>
    	    </batchtest>
    	    <classpath path="junit-4.10.jar:bin"/>
    	    <formatter usefile="false" type="brief" />
    	</junit>
    </target>
</project>

The test results won’t win a beauty contest, but there is a nice plugin called grepconsole you can use to make the result more expressive by coloring it. For example, you can color the “Tests run” line red if there are failures and green otherwise. Most of the remaining lines are less important and can be given a gray color. I use it extensively to improve the readability of the console output.

Our complete script also includes the commands to compile and weave the code (and packaging jars and wars, deleting directories and a lot more). A sketchy version of the script might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="default">
	<taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"
		     classpath="groovy-all-1.8.4.jar" />
	<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
		<classpath>
			<pathelement location="aspectjtools.jar" />
		</classpath>
	</taskdef>

	<target name="default" description="description">
		<groovyc destdir="classes/raw" srcdir="src">
			<javac destdir="classes/raw" srcdir="src">
			</javac>
		</groovyc>

		<target name="compile">
			<iajc destdir="classes/woven" inpath="rawclasses" classpath="aspectjrt.jar" />
		</target>
		<junit showoutput="true" haltonfailure="false" haltonerror="false" fork="true"
			   failureproperty="tests.failed" errorproperty="tests.failed">
			<batchtest todir="testresults">
				<fileset dir="JUnitTests">
					<include name="**/*.*" />
					<include name="**/*Test.java" />
				</fileset>
			</batchtest>
			<classpath path="junit-4.10.jar:classes/woven" />
			<formatter usefile="false" type="brief" />
		</junit>
	</target>
</project>

2 thoughts on “Lombok, AspectJ and JUnit

  1. Just wish to say your article is as astounding. The clearness in your
    submit is just excellent and i can suppose you’re knowledgeable in this subject.

    1. Thanks! Oh, and would you mind not to add spam to your comment next time? I won’t publish it anyways, so stop wasting your time :).

Leave a Reply

Your email address will not be published.