// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1
アーキテクチャテストのモチベーション
16 日目の ArchUnit 実践:同一パッケージからのみ呼び出されるメソッドの可視性をパッケージプライベートまたはプライベートに強制する の応用。
アーキテクチャテストの実装
package com.example;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaAccess;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.domain.JavaModifier;
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.methods;
class ArchitectureTest {
// 検査対象のクラス
private static final JavaClasses CLASSES =
new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.example");
@Test
void 自クラスからのみ呼び出されるメソッドはプライベートにする() {
methods()
.that(new DescribedPredicate<>("are public or are package private") {
@Override
public boolean apply(final JavaMethod method) {
return ! method.getModifiers().contains(JavaModifier.PRIVATE)
&& ! method.getModifiers().contains(JavaModifier.PROTECTED);
}
})
.and(new DescribedPredicate<>("that are only called in declared class") {
@Override
public boolean apply(final JavaMethod method) {
return method.getAccessesToSelf()
.stream()
.map(JavaAccess::getOriginOwner)
.allMatch(callerClass
-> callerClass.getFullName().equals(method.getOwner().getFullName()));
}
})
.should()
.bePrivate()
.check(CLASSES);
}
}