Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java custom Annotation aggregate multiple annotations

Im writing a TestCases for my RestControllers
For each ControllerTest calss I use the following annotations

@WebAppConfiguration
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebConfig.class, TestAppConfig.class})

So, I decided to define my own annotation witch contain all those annotations like this

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@WebAppConfiguration
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebConfig.class, TestAppConfig.class})
public @interface ControllerTest {
}

Then, I used only one annotation for all my ControllerTest classes

@ControllerTest
public class XXControllerTest {
}

After this modification the tests failed with

java.lang.IllegalArgumentException: WebApplicationContext is required
    at org.springframework.util.Assert.notNull(Assert.java:115)

And to make it work again it required me to add the @RunWith(SpringJUnit4ClassRunner.class) to the Test class

@ControllerTest
@RunWith(SpringJUnit4ClassRunner.class)
public class XXControllerTest {
}

My question is why my @ControllerTest annotation doesn't work while its contain the @RunWith(SpringJUnit4ClassRunner.class) annotation? is there anything special about the @RunWith annotation? or did I miss something?

PS: I use the same approach for Spring config classes and they work just fine.

like image 560
JafarKhQ Avatar asked Oct 26 '15 12:10

JafarKhQ


People also ask

Can we apply two annotations together?

It is also possible to use multiple annotations on the same declaration: @Author(name = "Jane Doe") @EBook class MyClass { ... } If the annotations have the same type, then this is called a repeating annotation: @Author(name = "Jane Doe") @Author(name = "John Smith") class MyClass { ... }

Can you apply more than one annotation on a target in Java?

You can repeat an annotation anywhere that you would use a standard annotation. For example, you have a class for handling unauthorized access exceptions.

Is @component is a meta annotation?

They all act the same because they are all composed annotations with @Component as a meta-annotation for each of them.

What is @interface annotation in Java?

Annotation is defined like a ordinary Java interface, but with an '@' preceding the interface keyword (i.e., @interface ). You can declare methods inside an annotation definition (just like declaring abstract method inside an interface). These methods are called elements instead.


1 Answers

This mechanism, where you can have "meta-annotations" that are themselves annotated with other annotations, which then apply to the class on which you put your meta-annotation, is something that is specific to the Spring Framework. It is not a standard feature of Java annotations.

It doesn't work because JUnit does not understand this mechanism. The @RunWith annotation is a JUnit annotation. JUnit does not understand that it should look at the annotations that are on your @ControllerTest meta-annotation.

So, this mechanism works with annotations that are processed by Spring, but not with annotations that are processed by other tools such as JUnit.

like image 113
Jesper Avatar answered Sep 28 '22 11:09

Jesper