LoginSignup
1
0

More than 3 years have passed since last update.

ArchUnit 実践:実行環境やフレームワークへの依存を禁止するアーキテクチャテスト

Last updated at Posted at 2020-12-04
// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* Spring Boot 2.4.0
* JUnit 5.7.0
* ArchUnit 0.14.1

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

ドメイン層は技術的な詳細に依らず、ビジネスのコアロジックを表現します。それらは特定の実行環境やフレームワークとも疎であるべきです。

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

ドメイン層は Web 実行環境 (Java Servlet) に依存しない

package com.example;

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.noClasses;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void ドメイン層はWeb実行環境に依存しない() {
        noClasses().that().resideInAPackage("com.example.domain..")
                .should()
                .dependOnClassesThat().resideInAPackage("javax.servlet..")
                .check(CLASSES);
    }
}

ドメイン層は Web アプリケーションフレームワーク (Spring Framework) に依存しない

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 org.springframework.transaction.annotation.Transactional;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void ドメイン層はWebアプリケーションフレームワークに依存しない() {
        noClasses().that().resideInAPackage("com.example.domain..")
                .should()
                .dependOnClassesThat(new DescribedPredicate<>("are part of the Spring Framework") {
                    /**
                     * @param clazz 検査対象のクラスが依存するクラス
                     * @return 検査対象のクラスが依存するクラスが Spring Framework のクラスである場合、true
                     */
                    @Override
                    public boolean apply(final JavaClass clazz) {
                        return clazz.getPackageName().startsWith("org.springframework")
                                // 特定のアノテーションへの依存は許可
                                && ! clazz.isEquivalentTo(Transactional.class);
                    }
                })
                .check(CLASSES);

    }
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0