I would like to write an ArchUnit test which says:
"the classes that are interfaces should have a name ending with Interface, but not the @interface
ones (they are annotations)".
For instance, this should be OK:
// Interface definition
interface AnimalInterface {
void animalSound(); // abstract method
void sleep(); // abstract method
}
But this should not
// Interface definition
interface Animal {
void animalSound(); // abstract method
void sleep(); // abstract method
}
But also (and this is the part I am having issues with):
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Constraint(validatedBy = SomethingValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidSomething {
String message() default "Invalid request data";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Should not be taken into account in this test, since it is @interface
, not interface
.
I tried to achieve this by writing the following code:
@Test
void interfacesShouldHaveNamesEndingWithTheWordInterface() {
classes().that().areInterfaces().should().haveNameMatching(".*Interface").check(importedClasses);
}
But this would fail for the @interface
part.
How to enhance the test to "ignore" "filter out" annotations?
You can use the DescribedPredicate<JavaClass>
JavaClass.Predicates.ANNOTATIONS
, or the corresponding fluent API for ArchRule
s, to exclude annotations from your rule:
@ArchTest
ArchRule rule = classes()
.that().areInterfaces()
.and().areNotAnnotations()
.should().haveNameMatching(".*Interface");