ArchUnit rules and arrays


Posted by Steven

ArchUnit can be used to test dependencies between packages in Java. I use it to test that application slices do not depend on each other, but are disjunct:

  1. @Test
  2. public void disjunctPackages() {
  3. JavaClasses importedClasses = new ClassFileImporter().importPackages("de.stevenschwenke.java.blubber");
  4. SliceRule sliceRule = slices().matching("de.stevenschwenke.java.blubber.(*)..").should().notDependOnEachOther();
  5. sliceRule.check(importedClasses);
  6. }

Sometimes, certain packages are used by other slices. A good example are "common", "base" or "share" packages that include data transfer objects. These packages can be excluded like this:

  1. @Test
  2. public void disjunctPackages() {
  3. JavaClasses importedClasses = new ClassFileImporter().importPackages("de.stevenschwenke.java.blubber");
  4. SliceRule sliceRule = slices().matching("de.stevenschwenke.java.blubber.(*)..").should().notDependOnEachOther()
  5. .ignoreDependency(alwaysTrue(), nameMatching("de\\.stevenschwenke\\.java\\.blubber\\.base\\..*"));
  6. sliceRule.check(importedClasses);
  7. }

An interesting problem arises when a class does not refer to a base-class in a single-fashioned way, let's say like this:

  1. private SomeBaseClass someBaseClass;

... but as an array like this:

  1. private SomeBaseClass[] someBaseClass;

Arrays are of different type than the class they come with. They also live in another package. Hence, the sliceRule shown above will fail:

  1. java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'slices matching 'de.stevenschwenke.java.blubber.(*)..' should not depend on each other' was violated (1 times):
  2. Slice xyz depends on Slice base:
  3. Constructor <de.stevenschwenke.java.xyz.SomeClass.<init>(...)> has parameter of type <[Lde.stevenschwenke.java.base.SomeBaseClass;> in (SomeClass.java:0)

ArchUnit seems to "place" arrays in the package of the base class, beginning with "[L", see this discussion. Hence, I use this workaround to cover arrays for the use case stated above:

  1. .ignoreDependency(alwaysTrue(), nameMatching("\\[Lde\\.stevenschwenke\\.java\\.base\\..*"))

UPDATE

Thanks to a tweet from the ArchUnit-team, I changed my code to this solution which is way better than mine:

  1. .ignoreDependency(alwaysTrue(), resideInAPackage("de.stevenschwenke.java.base..*"))
Category: 
Share: