By using a library called ** ArchUnit **, it is possible to check whether the Java source code violates the architecture by unit testing.
I will introduce what you can do with ArchUnit and what kind of code it will actually be.
ArchUnit is an open source library that helps you run unit tests on the Java architecture. This is a noteworthy library that was also published in TECHNOLOGY RADAR.
With ArchUnit, you can check the following with unit tests. (*)
is accessed only from the class with
@ Transactional`.Controller → Service → Persistence
are not allowed access.Architectural violations are less likely to occur.
Traditionally, to keep the architecture clean
I think that there were many analog measures such as. Therefore, if any human error occurs, the architecture-violating code will go into the master branch.
When using ArchUnit, unit tests can detect architecture violations, so CI can check for architecture violations. So, ** if the tests are written correctly **, the merged code cannot cause an architecture violation.
The installation method is described in here. The code shown below can be found at here. (Tested with JUnit 5)
When writing a test using ArchUnit, first give @AnalyzeClasses
to the test class.
The classes included in the package specified by packages
will be tested.
@AnalyzeClasses(packages = "nannany.arch.check.archunit")
public class ArchitectureTest {
The following checks the architecture that a package with service
in the package name cannot depend on a package with controller
in the package name.
/**
*Service package subordinate does not depend on controller
*/
@ArchTest
public static final ArchRule servicesCantDependOnController = noClasses()
.that().resideInAnyPackage("..service..")
.should().dependOnClassesThat().resideInAPackage("..controller..");
The description method is an image of writing the class to be tested on the left side of should ()
and the rule on the right side of should ()
.
In the above example, for noClasses (). That () .resideInAnyPackage (".. service .. ")
, the class contained in the package named service
should be on the right side ofshould ()
. It means that there is no class that fits the rule **.
For dependOnClassesThat (). ResideInAPackage (".. controller .. ");
, it expresses the rule that it depends on the package named controller
.
ArchUnit provides support for typical architectures. Currently, [Multitier Architecture](https://ja.wikipedia.org/wiki/%E5%A4%9A%E5%B1%A4%E3%82%A2%E3%83%BC%E3%82%AD % E3% 83% 86% E3% 82% AF% E3% 83% 81% E3% 83% A3) and Onion Architecture (Hexagonal Architecture)) There seems to be support for.
In the following, we use methods that support multi-tier architectures to check for access between layers other than Controller → Service → Persistence
.
/**
*Using layered Architecture
*/
@ArchTest
public static final ArchRule layeredArchitecture = layeredArchitecture()
.layer("Controllers").definedBy("nannany.arch.check.archunit.controller")
.layer("Services").definedBy("nannany.arch.check.archunit.service")
.layer("Repositories").definedBy("nannany.arch.check.archunit.repository")
.whereLayer("Controllers").mayNotBeAccessedByAnyLayer()
.whereLayer("Services").mayOnlyBeAccessedByLayers("Controllers")
.whereLayer("Repositories").mayOnlyBeAccessedByLayers("Services");
https://www.archunit.org/ https://www.thoughtworks.com/radar/tools/archunit
Recommended Posts