// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1
アーキテクチャテストのモチベーション
- パッケージ内に閉じた関心事を、パッケージ外に対して隠蔽したい
- パッケージ外からの想定外の依存(結合)が生まれることを言語仕様レベルで防止したい
- 公開範囲を限定することで、保守性(理解容易性、変更容易性)を向上したい
アーキテクチャテストの実装
package com.example;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.Dependency;
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()
.arePublic()
.and(new DescribedPredicate<>("only have dependent classes that reside in same package") {
@Override
public boolean apply(final JavaClass clazz) {
return clazz.getDirectDependenciesToSelf()
.stream()
.map(Dependency::getOriginClass)
.allMatch(dependentClass
-> dependentClass.getPackageName().equals(clazz.getPackageName()));
}
})
.should()
.notBePublic()
.check(CLASSES);
}
}