ArchUnit 実践:StringUtil(s) 多すぎ問題に負けない


// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1

アーキテクチャテストのモチベーション

フレームワークや複数のライブラリを導入すると、それぞれで独自に実装された StringUtil(s) クラスがコード補完に複数でてきてどれを使えばいいのか困る、ということはよくあります。

開発者によって使用する StringUtil(s) クラスが違ってくると、一貫性のない、想定外の依存を含んだコードになってしまいます。

例えば、「StringUtil(s) は org.apache.commons.lang3.StringUtils を使う」ということがプロジェクトのガイドラインとして決まっているのであれば、それをアーキテクチャテストによって担保できます。

アーキテクチャテストの実装

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 StringUtilsはApacheCommonsLang3のStringUtilsのみ使用可能() {
        classes()
            .should()
            .onlyDependOnClassesThat(new DescribedPredicate<>("org.apache.commons.lang3 の StringUtils クラス") {
                /**
                 * @param clazz 依存先のクラス
                 * @return 依存先のクラスが org.apache.commons.lang3.StringUtils である場合、true
                 */
                @Override
                public boolean apply(final JavaClass clazz) {
                    boolean isStringUtil = clazz.getSimpleName().endsWith("StringUtils")
                        || clazz.getSimpleName().endsWith("StringUtil");

                    if (! isStringUtil) {
                        // StringUtil(s) でないクラスは、このテストでの依存チェック対象外
                        return true;
                    }

                    return clazz.getPackageName().equals("org.apache.commons.lang3");
                }
            })
            .check(CLASSES);
    }
}