Archunit test
ArchUnit integrates nicely with the JUnit test framework, and so, they are typically used together. All we have to do is add the archunit-junit5 dependency to match our JUnit version:
<dependency> <groupId>com.tngtech.archunit</groupId> <artifactId>archunit-junit5</artifactId> <version>0.14.1</version> <scope>test</scope> </dependency>
Step 1:
The first step is to create a set of Java classes that will be checked for rules violations. We do this by instantiating the ClassFileImporter class and then using one of its importXXX() methods:
JavaClasses jc = new ClassFileImporter() .importPackages("com.baeldung.archunit.smurfs");
Step 2:
Let’s try to implement the first rule defined above using this API. We’ll use the classes() method as our anchor and add additional constraints from there:
Notice that we need to call the check() method of the rule we’ve created to run the check. This method takes a JavaClasses object and will throw an exception if there’s a violation.
Step3:
This all looks good, but we’ll get a list of errors if we try to run it against our code:
Why? The main problem with this rule is the onlyDependsOnClassesThat(). Despite what we’ve put in the package diagram, our actual implementation has dependencies on JVM and Spring framework classes, hence the error.
One way to solve this error is to add a clause that takes into account those additional dependencies:
With this change, our check will stop failing. This approach, however, suffers from maintainability issues and feels a bit hacky. We can avoid those issues rewriting our rule using the noClasses() static method as our starting point:
Of course, we can also point that this approach is deny-based instead of the allow-based one we had before. The critical point is that whatever approach we choose, ArchUnit will usually be flexible enough to express our rules.
ArchUnit offers the Library API, a collection of prepackaged rules that address common architecture concerns:
Here, layeredArchitecture() is a static method from the Architectures class. When invoked, it returns a new LayeredArchitecture object, which we then use to define names layers and assertions regarding their dependencies. This object implements the ArchRule interface so that we can use it just like any other rule.
Comments
Post a Comment