// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1
アーキテクチャテストのモチベーション
2 日目の ArchUnit 実践:依存関係を逆転した Layered Architecture のアーキテクチャテスト の、依存関係を逆転した Layered Architecture では、インフラストラクチャ層は依存関係の最上位に存在します。これは対象のクラス(インターフェイス)に代わって技術的詳細を実装するためであり、インフラストラクチャ層のクラスが他の層に依存してよいのは、そのインターフェイスを実装する場合のみです。他の層の具象クラスへの依存は禁止されるべきです。
アーキテクチャテストの実装
package com.example;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
class ArchitectureTest {
// 検査対象のクラス
private static final JavaClasses CLASSES =
new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.example");
@Test
void インフラストラクチャ層のクラスは他の層のインターフェイスにのみ依存できる() {
classes().that().resideInAPackage("com.example.infrastructure..")
.should()
.onlyDependOnClassesThat(new DescribedPredicate<>("他の層のインターフェイス") {
/**
* @param clazz 依存先のクラス
* @return 依存先のクラスが他の層の具象クラスである場合、false
*/
@Override
public boolean apply(final JavaClass clazz) {
if (! clazz.getPackageName().startsWith("com.example")) {
// サードパーティーライブラリなどへの依存はOK
return true;
}
if (clazz.getPackageName().startsWith("com.example.infrastructure")) {
// 同じインフラストラクチャ層のクラスへの依存はOK
return true;
}
if (clazz.isInterface()) {
// 他の層のインターフェイスへの依存はOK
return true;
}
return false;
}
})
.check(CLASSES);
}
}