I would like to check whether FOO.model is only accessed by FOO.service and BAR.model is only accessed by BAR.service and so on.
Is there a way to achieve this with ArchUnit? Like (pseudocode)
classes()
.that().resideInAPackage("{PLACEHOLDER}.model")
.should().onlyBeAccessed().byAnyPackage("{PLACEHOLDER}.service");
I’m aware I could write a test that iterates over all FOO, BAR etc packages, or write a separate test for every package, but I’m looking for a generic out-of-the-box solution where I do not have to update my test class every time I introduce a new package.
Advertisement
Answer
You can use a custom condition to test the origin of each access:
classes()
.that().resideInAPackage("..model")
.should(new ArchCondition<JavaClass>("only be accessed from the corresponding service package") {
@Override
public void check(JavaClass javaClass, ConditionEvents conditionEvents) {
javaClass.getAccessesToSelf().forEach(access -> {
String originPackageName = access.getOrigin().getOwner().getPackageName();
String targetPackageName = access.getTarget().getOwner().getPackageName();
String expectedOriginPackageName = targetPackageName.replace(".model", ".service");
boolean satisfied = originPackageName.equals(expectedOriginPackageName);
conditionEvents.add(new SimpleConditionEvent(access, satisfied, access.getDescription()));
});
}
});
(There are probably more sophisticated ways to construct expectedOriginPackageName…)