Search code examples
javajunitannotations

How can I fix ClassNotFoundException when using getAnnotation(Test.class) in my Java program with JUnit?


I have a program where I want to take methods from a class and verify if they have the @Test annotation, and if they do, to output the names of the methods. The problem is when I call getAnnotation(Test.class) it doesn't find Test class in java ClassLoader and BuiltinClassLoader and throws ClassNotFoundException.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.annotation.Annotation;
import org.junit.jupiter.api.Test;

public class Lab12 {
    public static void main(String[] args) {
        if(args.length < 1) {
            System.err.println("Input: <class name>");
        }
        try {
            Class testedClass = Class.forName(args[0].toString());
            Package testedPackage = testedClass.getPackage();
            System.out.println("Name of the class: " + testedClass.getName());
            System.out.println("Name of the package: " + testedPackage.getName());
            Method[] classMethods = testedClass.getDeclaredMethods();
            for(Method method : classMethods) {
                System.out.println("So far good");
                if(method.getAnnotation(Test.class) != null) {
                    if(method.getParameterCount() == 0) {
                        method.setAccessible(true);
                        method.invoke(null);
                        System.out.println("Test method invoked: " + method.getName());
                    }
                }
            }
        }
        catch(ClassNotFoundException ex) {
            System.err.println(ex);
        }
        catch(IllegalAccessException ex) {
            System.err.println(ex);
        }
        catch(InvocationTargetException ex) {
            System.err.println(ex);
        }
    }
}

The error that I receive:

Exception in thread "main" java.lang.NoClassDefFoundError: org/junit/jupiter/api/Test   
        at Lab12.main(Lab12.java:20)
Caused by: java.lang.ClassNotFoundException: org.junit.jupiter.api.Test
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 1 more

I have implemented in the pom.xml the dependencies for the JUnit api and they are recognized in the program.

If I change the parameter of getAnnotation(Override.class, for example), it works. I have imported org.junit.jupiter.api.Test in the program.


Solution

  • Instead of running the program as:

    java Lab12 className
    

    Try running it like this:

    java -cp .;<path_to_junit_jar> Lab12 <className>
    

    <path_to_junit_jar> - should be the full path to the junit.jar. This needs to be given so that JVM also knows at run time where that jar file is. pom.xml will not be used when your run your program. It will only be used when you run mvn build, etc. maven commands. So, at run time, your command does not find JUnit at all.

    Also note that, when you run that test method via reflection from your class - e.g. method.invoke(null) - if your test class has further dependencies - e.g. mockito or DB jar (e.g. mysql connector/j) or anything else - then those will also need to be added in -cp list of class path jars.