Search code examples
javajunitreflectionannotations

Reading custom annotation for JUNIT


I have a custom annotation which I use as config to start off one time set-up for Junit.

@Target(TYPE) @Retention(RUNTIME)
public @interface MyAnnotation{
   String host();
   int port();
}

Test class:

@MyAnnotation(host="0.0.0.0", port=4567)
public class MyTest extends MyAbstractClass{
   @Test
   public void myTest(){
      //do testy things
   }   
}

Superclass:

public class MyAbstractClass{

   @BeforeAll
   public static void start(){
    Config cfg = readConfig();
    //Use config to do one time set-up
   }

   private static Config readConfig(){
      MyAnnotation ann = MyTest.class.getAnnotation(MyAnnotation.class);
      return new Config(ann.host(), ann.port());
   }
}

So currently, I hardcode the name of the test class (MyTest) in readConfig(..). This won't work when I add a second test class.

One way to solve it is:

  • Add another @BeforeAll method in MyTest which will call the @BeforeAll in super-class and pass the class name as a param.

However, I am curious if I can read the name of the executing subclass in the superclass via some reflexion magic. Any ideas are most welcome.

Thanks


Solution

  • The presence of the @BeforeAll annotation suggests you are using JUnit 5. In this case, you can use.

    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.TestInfo;
    
    public class MyAbstractClass {
        @BeforeAll
        public static void start(TestInfo ti) {
            Config cfg=readConfig(ti.getTestClass().orElseThrow(IllegalStateException::new));
            //Use config to do one time set-up
        }
    
        private static Config readConfig(Class<?> testClass) {
             MyAnnotation ann = testClass.getAnnotation(MyAnnotation.class);
             return new Config(ann.host(), ann.port());
        }
    }
    

    See also the TestInfo API documentation.

    This is not “Reflection Magic” but a feature provided by JUnit itself, but it’s also only JUnit which knows that the invocation of a static method annotated with @BeforeAll is associated with a particular test class it is going to process.