I want to define an ArchUnit rule that prevents the use of the EntityManager
class outside of my repository classes. I have one exception to this rule, a single call to entityManager.detach
in com.myapp.EventService
.
Currently my JUnit 5 rule looks like this:
@ArchTest
static final ArchRule onlyRepositoriesMayUseEntityManager = noClasses()
.that().resideOutsideOfPackage("com.myapp.repository..")
.and(are(not(equivalentTo(EventService.class))))
.should().accessClassesThat().areAssignableTo(EntityManager.class);
But this will allow any method of EntityManager
to be used in EventService
. I would rather either of the following
detach
method to be used in EventServicedetach
method to be used anywhere outside of the repositories.should()
.accessTargetWhere(
…
allows you to specify a DescribedPredicate
for a JavaAccess
(not to be confused with its AccessTarget
🤯 – cf. ArchUnit's domain model).
With that, a solution for your option 1 could be (using DescribedPredicate.describe
):
@ArchTest
ArchRule onlyRepositoriesMayUseEntityManager = noClasses()
.that().resideOutsideOfPackage("com.myapp.repository..")
.should().accessTargetWhere(describe("owner is assignable to EntityManager", access ->
access.getTargetOwner().isAssignableTo(EntityManager.class) &&
!(access.getOriginOwner().isEquivalentTo(EventService.class) &&
access.getTarget().getName().equals("detach"))
));