Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] Load time weaving with maven and surefire fails

Hi folks,

Following the guidelines from the link below, I am using load time weaving in for my unit test.

[1] http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg09286.html

Unfortunately this results in the following error message :-(

[INFO] Surefire report directory: <source-path>\target\surefire-reports
java.lang.NoClassDefFoundError: null
Caused by: java.lang.ClassNotFoundException: null
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: null.  Program will exit.
Exception in thread "main"

Anyone a clue?

Let me explain what I am trying to achieve. I want to increase code overage for my utility classes (private constructor). See also:

http://stackoverflow.com/questions/4520216/how-to-add-test-coverage-to-a-private-constructor

There are 2 straight forward ways to achieve this:
1) Add a testcase and use reflection instantiate the private constructor (described in previouse link). 2) Add a static section to my utility class and instantiate the class there, like:
        static {
            new MyClass();
        }

The first is rejected because I need to do this for every utility class and the test is just for the sake of increasing coverage, not for testing functionality. The second one I reject because it polutes my code for the sake of code coverage.

I came up

I came up with a solution which is more appealing to me. Creating an Aspect to achieve the same thing as solution 2. However I do not like this Aspect to be part of my actual code. So I decided to use load time weaving during unit testing. This way the additional coverage only shows up on test utility classes.

How did I do this. First of all, here's the actual aspect:

        package <my aspect package>.aspects;

        import java.lang.reflect.Constructor;
        import java.lang.reflect.Modifier;

        /**
         * Special aspect to increase code coverage on classes with private
         * constructors.
         *
         * @author Minto van der Sluis
         */
        public aspect PrivateConstructorCoverage {

// Joinpoint for static initialization blocks of all classes in the
            // populators package.
pointcut staticInit() : staticinitialization(<my utility class package>.populators..*);

            before(): staticInit() {
// Determine the class on which this advice is currently working. Class<?> clazz = thisJoinPoint.getSignature().getDeclaringType();
                Constructor<?> constructor = null;
                try {
                    // Use reflection to get to the default constructor.
                    constructor = clazz.getDeclaredConstructor();
                } catch( NoSuchMethodException e ) {
System.out.println( "Missing default constructor for: " + clazz.getName() );
                }

// Only instantiate the class if a private default constructor exists. if ( constructor != null && Modifier.isPrivate( constructor.getModifiers() )) {
                    constructor.setAccessible(true);
                    try {
System.out.println( "Increasing coverage by calling: new " + clazz.getSimpleName() + "()" );
                        constructor.newInstance();
                    } catch (Exception e) {
                        // Instantiating failed
System.out.println( "Instantiation failed due to: " + e.getMessage() );
                    }
                }
            }
        }

This aspect is included in 'src/test/java'. For the sake of load time weaving I added the following aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aspectj PUBLIC "//AspectJ/" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd";>
<aspectj>
<weaver options="-verbose">
<include within="<my package>.populators..*"/>
<exclude within="<my package>.populators..*Test"/>
</weaver>

<aspects>
<aspect name="<my aspect package>.PrivateConstructorCoverage"/>
</aspects>
</aspectj>

I also made a small change to the surefire configuration (see [1]). Instead of pointing to a locally installed version of the aspectjweaver (${basedir}/../lib/). I changed the surefire configuration to point to the one in my local maven repository. To make sure aspectjweaver is actually in my local repository, I added a dependency to it in my pom file with scope provided.

<argLine>-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar ${debug}</argLine>

Unfortunately due to non disclosure I had to erease a few references to my currect project. In these places I used the following placeholders:
<my package>
<my aspect package>

Does anyone know why surefire won't start?

Regards,

misl

--
ir. ing. Minto 'misl' van der Sluis
Xup BV

Mobiel: +31 (0) 626 014541



Back to the top