Search code examples
javaunit-testingjunitarchunit

Using archunit to enforce all sub-packages only reference themselves of a "common" package


If i have a package structure like:

org.myapp

  • common
  • feature1
  • feature2
  • ...

I would like to write an archunit test that checks if all classes inside the feature packages only reference other classes inside the same feature package or external classes or classes in the common package.

I've been able to implement this test using layeredArchitecture (see below) but that forces me to actually hardcode the names of each feature branch, and i would like to make it future proof so that if one more feature package is added the test will check it as well.

 @ArchTest
    public static final ArchRule layer_arquitecture = layeredArchitecture().consideringAllDependencies()
        .layer("common").definedBy("org.myapp.common..")
        .layer("feature1").definedBy("org.myapp.feature1..")
        .layer("feature1").definedBy("org.myapp.feature2..")
        .whereLayer("feature1").mayNotBeAccessedByAnyLayer()
        .whereLayer("feature2").mayNotBeAccessedByAnyLayer();

Solution

  • I think that SlicesRuleDefinition might help, see also SlicesIsolationTest from ArchUnit-Examples.

    @ArchTest
    public static final ArchRule featuresShouldBeIndependent = SlicesRuleDefinition
            .slices().matching("org.myapp.(*)..")
            .should().notDependOnEachOther();
    

    Unless you can find a PackageMatcher (like "org.myapp.(feature*)..") that does not pick up "org.myapp.common..", you may have to work with SliceRule's ignoreDependency, probably like this:

    @ArchTest
    public static final ArchRule featuresShouldBeIndependent = SlicesRuleDefinition
            .slices().matching("org.myapp.(*)..")
            .should().notDependOnEachOther()
            .ignoreDependency(
                /* originPredicate = */ DescribedPredicate.alwaysTrue(),
                /* targetPredicate = */ JavaClass.Predicates.resideInAPackage("org.myapp.common..")
            );