ArchUnit
ArchUnit copied to clipboard
JavaClass.Predicates API: missing .extends(String/class/DescribedPredicate)
I am trying to write a test that verifies that classes that are inherited from fulfill certain properties.
However currently there is only JavaClass.Predicates.implement for interfaces, JavaClass.Predicates.assigneableTo/From and the latter do also return themselves if matching.
Stupid example demonstrating the problem - this matches each class ending in "FOO" with itself:
@ArchTest
public ArchRule thisSadlyMatchesAllClassesEndingWithFOO =
noClasses()
.that().haveSimpleNameEndingWith( "FOO" )
.should( ArchCondition.from( JavaClass.Predicates.assignableTo( JavaClass.Predicates.simpleNameContaining( "FOO" ) ) ) );
My current custom predicate uses this logic:
@Override
public boolean test( JavaClass javaClass ) { // Could be added as JavaClass.Predicates.extends
return Stream.concat(
// leave out javaclass.this which is contained in javaClass.getClassHierarchy()
javaClass.getAllRawSuperclasses().stream(),
javaClass.getAllRawInterfaces().stream()
)
.anyMatch( innerPredicate );
}
Is there a better way to do it? I've not put up a PR, as I didn't know what to do about performance and memoization of the classHierarchy.
Sorry for the late reply! I don't think there is any better way right now. I guess a strict extends vs assignableTo could make sense 🤔 What's your concrete use case where you need this?
I usually use ArchUnit to test for dangerous or unwanted API use ;)
In this concrete case I actually test JUnit testcases for some parallelization edge cases that are QUITE hard to find otherwise:
No (UnitTest)classes should extend classes that define a @BeforeAll method and don't ... <some custom matching logic>
And if I use the assignableTo it obviously fails on most UnitTests defining a @BeforeAll as it includes this
I had this case on other occasions where I want to express don't do this strange stuff to OTHER classes/classes you inherit from - doing it to yourself is fine
Does that help?