Minto van der sluis
2011-02-12 21:33:37 UTC
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
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
ir. ing. Minto 'misl' van der Sluis
Xup BV
Mobiel: +31 (0) 626 014541