Dieses Mal möchte ich über eine Bibliothek namens ArchUnit schreiben, die mich besonders interessiert hat an Technology Radar Vol.19, die im November 2018 angekündigt wurde. Überlegen.
Dieser Artikel zeigt das Ergebnis der tatsächlichen Bewegung der Hand unter Bezugnahme auf die offiziellen Informationen. Wenn Sie sie jedoch mit ArchUnit implementieren, handelt es sich nicht um diesen Artikel, sondern um das offizielle [ArchUnit-Benutzerhandbuch](https: //). Weitere Informationen finden Sie unter www.archunit.org/userguide/html/000_Index.html. Wenn Sie im Artikel etwas falsch finden, kommentieren Sie dies bitte.
ArchUnit ist eine Bibliothek zum Testen der Architektur für in Java / Kotlin geschriebene Anwendungen. Da ArchUnit selbst OSS ist, wird der Quellcode auf GitHub veröffentlicht. https://github.com/TNG/ArchUnit/blob/master/licenses/asm.license
Mit ArchUnit können Sie verschiedene Architekturtests durchführen, z. B. Abhängigkeiten zwischen Paketen und Klassen, Überprüfen der Klassenverpackung, Überprüfen von Zirkelverweisen und mehr. Darüber hinaus ist ArchUnit eine Bibliothek, die die in Evolutionary Architecture [Technology Radar]( Es wird unter https://www.thoughtworks.com/radar/tools/archunit vorgestellt. Die Anpassungsfunktion ist ein Index zum Messen der Eigenschaften einer Architektur. Die Anpassungsfunktion kann realisiert werden, indem der Test mit ArchUnit in CI / CD integriert wird. Weitere Informationen zur Anpassungsfunktion finden Sie unter Evolutionäre Architektur und [Technology Radar Vol.18](https: //www.thoughtworks). Siehe com / Radar / Techniken / Architektur-Fitness-Funktion).
Von hier aus möchte ich den eigentlichen Test mit ArchUnit in die Codebasis einführen. Ich verweise auf das ArchUnit-Benutzerhandbuch. Wenn Sie weitere Informationen benötigen, lesen Sie dies bitte unbedingt. Es wird angenommen, dass die Betriebsumgebung Maven 3.5.4, Spring Boot 2.1.0, Kotlin 1.3 und JUnit 4 ist.
Fügen Sie für JUnit4 / Maven Folgendes zu pom.xml hinzu.
pom.xml
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit4</artifactId>
<version>0.9.3</version>
<scope>test</scope>
</dependency>
Laden Sie ArchUnitRunner beim Erstellen einer Testklasse mithilfe der Annotation @RunWith wie unten gezeigt. Geben Sie außerdem das Basispaket der zu testenden Anwendung mit der Annotation @AnalyzeClasses an und fügen Sie der Testmethode "@ ArchTest" hinzu.
Sample.kt
@RunWith(ArchUnitRunner::class)
@AnalyzeClasses(packages = ["com.dais39.sample.app"])
class TestApplicationRules {
@ArchTest
fun test(classes: JavaClasses) {
//Testprozess
}
}
Wenn Sie Paketabhängigkeiten testen möchten, schreiben Sie Code wie folgt: In ArchUnit wird als grundlegender Testablauf "Regel" in der Methodenkette beschrieben, und schließlich wird der Test durch Aufrufen von "check ()" ausgeführt. Eine Funktion von ArchUnit ist, dass Sie ausdrucksstarken Code schreiben können, indem Sie Methoden verbinden. Das folgende Beispiel stellt sicher, dass alle Klassen, die auf Klassen im Anwendungspaket verweisen, in der Präsentation oder im Anwendungspaket platziert werden. Der Test schlägt fehl, wenn von einem anderen Paket verwiesen wird.
Sample.kt
@RunWith(ArchUnitRunner::class)
@AnalyzeClasses(packages = ["com.dais39.sample.app"])
class TestApplicationRules {
@ArchTest
Klassen in der unterhaltsamen Anwendungsschicht sind unabhängig von anderen Klassen als der Präsentationsschicht(classes: JavaClasses) {
val rules = ArchRuleDefinition.classes().that().resideInAPackage("..application..")
.should().onlyBeAccessed().byClassesThat().resideInAPackage("..presentation..")
rules.check(classes)
}
}
Hier ist ein Test, wenn Sie sicherstellen möchten, dass nur die Controller-Klasse auf die Service-Klasse zugreift: Sie können haveNameMatching ()
verwenden, um Muster mit regulären Ausdrücken abzugleichen, aber Sie können haveSimpleName ()
verwenden, um den Klassennamen direkt anzugeben. Es gibt andere Methoden für den Mustervergleich.
Sample.kt
@ArchTest
Auf die fun Service-Klasse wird nur über die Controller-Klasse zugegriffen(classes: JavaClasses){
val rules = ArchRuleDefinition.classes().that().haveNameMatching(".*Service")
.should().onlyBeAccessed().byClassesThat().haveNameMatching(".*Controller")
rules.check(classes)
}
Ein Test, der garantiert, dass sich eine Klasse in einem bestimmten Paket befindet, lautet wie folgt:
Sample.kt
@ArchTest
Klassen mit Namen, die mit fun ToDoService beginnen, werden in das Anwendungspaket eingefügt(classes: JavaClasses){
val rules = ArchRuleDefinition.classes().that().haveSimpleNameStartingWith("ToDoService")
.should().resideInAPackage("..application..")
rules.check(classes)
}
Ein Test, der garantiert, dass eine Schnittstelle nur von einer Klasse mit bestimmten Bedingungen implementiert wird, wird wie folgt geschrieben. Im folgenden Beispiel ist die Bedingung eine Klasse, die mit der Zeichenfolge endet, die mit haveSimpleNameEndingWith ()
angegeben wurde.
Sample.kt
@ArchTest
fun ToDoServiceImpl implementiert die ToDoService-Schnittstelle(classes: JavaClasses){
val rules = ArchRuleDefinition.classes().that().implement(ToDoService::class.java)
.should().haveSimpleNameEndingWith("ToDoServiceImpl")
rules.check(classes)
}
Im Folgenden finden Sie einen Test, der sicherstellt, dass auf die ToDoService-Klasse nur von der Klasse mit @ RestController
zugegriffen werden kann.
Sample.kt
@ArchTest
Auf die unterhaltsame ToDoService-Klasse wird nur von der Klasse mit der RestController-Annotation zugegriffen(classes: JavaClasses){
val rules = ArchRuleDefinition.classes().that().areAssignableTo(ToDoService::class.java)
.should().onlyBeAccessed().byClassesThat().areAnnotatedWith(RestController::class.java)
rules.check(classes)
}
Mit ArchUnit können Sie Tests schreiben, die eine Paketstruktur gewährleisten, die der Layer-Architektur entspricht. Derzeit unterstützt es nur Layer-Architektur, aber es scheint, dass es in Zukunft hexagonale Architektur und saubere Architektur unterstützen wird. Im Folgenden finden Sie die Tests, die eine Architektur garantieren, die DIP (Dependency Reversal Principle) auf die Layer-Architektur anwendet.
Sample.kt
@ArchTest
Die Struktur der Spaßanwendung folgt der Ebenenarchitektur(classes: JavaClasses){
val rules = Architectures.layeredArchitecture()
.layer("Presentation").definedBy("..presentation..")
.layer("Application").definedBy("..application..")
.layer("Domain").definedBy("..domain..")
.layer("Infrastructure").definedBy("..infra..")
.whereLayer("Presentation").mayNotBeAccessedByAnyLayer()
.whereLayer("Application").mayOnlyBeAccessedByLayers("Presentation")
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Infrastructure")
.whereLayer("Infrastructure").mayNotBeAccessedByAnyLayer()
rules.check(classes)
}
Wenn Sie einen Test erstellen möchten, der prüft, ob in Ihrer Anwendung Zirkelverweise vorhanden sind, schreiben Sie: Geben Sie das Zielpaket mit "matching ()" an.
Sample.kt
@ArchTest
Spaß Rundschreiben existiert nicht(classes: JavaClasses){
val rules = SlicesRuleDefinition.slices().matching("com.dais39.sample.app.(*)..").should().beFreeOfCycles()
rules.check(classes)
}
Was ist ArchUnit diesmal? Was können Sie mit ArchUnit tun? Das habe ich vorgestellt. Es ist eine Bibliothek, die ich persönlich sehr empfehlen kann, um die Architektur testen und Kotlin unterstützen zu können. Ich hoffe, dass sich mehr Menschen für diesen Artikel interessieren.
Recommended Posts