ArchUnit 연습: Layered Architecture 아키텍처 테스트

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

레이어 종속성





Java 프로젝트의 패키지 구성





아키텍처 테스트 구현


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.library.Architectures.layeredArchitecture;

class ArchitectureTest {

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

    @Test
    void レイヤードアーキテクチャのアーキテクチャテスト() {
        layeredArchitecture()
            // presentation パッケージを UI 層として定義
            .layer("ui").definedBy("com.example.presentation..")
            // application パッケージをアプリケーション層として定義
            .layer("app").definedBy("com.example.application..")
            // domain パッケージをドメイン層として定義
            .layer("domain").definedBy("com.example.domain..")
            // infrastructure パッケージをインフラストラクチャ層として定義
            .layer("infra").definedBy("com.example.infrastructure..")

            // UI 層はどの層からも依存されない
            .whereLayer("ui").mayNotBeAccessedByAnyLayer()
            // アプリケーション層は UI 層からのみ依存される
            .whereLayer("app").mayOnlyBeAccessedByLayers("ui")
            // ドメイン層は UI 層、アプリケーション層からのみ依存される
            .whereLayer("domain").mayOnlyBeAccessedByLayers("ui", "app")
            // インフラストラクチャ層は UI 層、アプリケーション層、ドメイン層から依存される
            .whereLayer("infra").mayOnlyBeAccessedByLayers("ui", "app", "domain")

            .check(CLASSES);
    }
}

아키텍처 테스트 실행 예(테스트 실패 예)



애플리케이션 계층의 Service 클래스가 프레젠테이션 계층의 Helper 클래스에 의존하고 있다는 아키텍처 위반을 감지한 가정에서의 테스트 실패 예.
$ ./gradlew clean check

> Task :test

ArchitectureTest > レイヤーアーキテクチャ() FAILED
    java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'Layered architecture consisting of
    layer 'ui' ('com.example.presentation..')
    layer 'app' ('com.example.application..')
    layer 'domain' ('com.example.domain..')
    layer 'infra' ('com.example.infrastructure..')
    where layer 'ui' may not be accessed by any layer
    where layer 'app' may only be accessed by layers ['ui']
    where layer 'domain' may only be accessed by layers ['ui', 'app']
    where layer 'infra' may only be accessed by layers ['ui', 'app', 'domain']' was violated (2 times):
    Constructor <com.example.application.employee.EmployeeRegisterService.<init>(com.example.presentation.JsonRenderHelper)> has parameter of type <com.example.presentation.JsonRenderHelper> in (EmployeeRegisterService.java:0)
    Field <com.example.application.employee.EmployeeRegisterService.jsonRenderHelper> has type <com.example.presentation.JsonRenderHelper> in (EmployeeRegisterService.java:0)
        at com.tngtech.archunit.lang.ArchRule$Assertions.assertNoViolation(ArchRule.java:94)
        at com.tngtech.archunit.lang.ArchRule$Assertions.check(ArchRule.java:82)
        at com.tngtech.archunit.library.Architectures$LayeredArchitecture.check(Architectures.java:267)
        at com.example.ArchitectureTest.レイヤーアーキテクチャ(ArchitectureTest.java:69)

1 test completed, 1 failed

> Task :test FAILED

좋은 웹페이지 즐겨찾기