I have a package for which I want to check that all classes (these are entities that can get shipped over the net) do indeed implement the interface "java.io.Serializable". So I defined myself a rule like so (the actual rule has a few excludes but these are not relevant here):
@ArchTest
void checkSerializability(JavaClasses classes) {
ArchRule rule = ArchRuleDefinition.classes()
.that().resideInAnyPackage("..entities..")
.should().implement(Serializable.class)
;
rule.check(classes);
}
That rule works fine, except that a few classes implement a common interface that extends Serializable, i.e.:
interface IAction extends Serializable {
... some methods to be implemented declared here ...
}
The above ArchUnit-rule complains that this interface(-class) does not implement Serializable. In a sense that is true - strictly speaking it doesn't implement it, it just extends it.
But I didn't find an extends(<class>)
-method, so I can not phrase this condition as implements(Serializable.class).or().extends(Serializable.class)
.
So, how can can I teach ArchUnit to accept that interface as "implementing" Serializable and hence as valid?
Let me cite the JavaDoc: ClassesShould.implement
asserts that classes implement a certain interface. Note that this only matches non-interface classes that implement the supplied interface type (compare JavaClass.Predicates.implement(Class)
). For general assignability see beAssignableTo
, which in turn
asserts that classes are assignable to a certain type (compare Class.isAssignableFrom(Class)
terminology). A simple example for this predicate would be:
assignableTo(Object.class).test(importedStringClass); // → returns true
assignableTo(String.class).test(importedStringClass); // → returns true
assignableTo(List.class).test(importedStringClass); // → returns false
So you can use
ArchRule rule = ArchRuleDefinition.classes()
.that().resideInAnyPackage("..entities..")
.should().beAssignableTo(Serializable.class);