ArchUnit 연습: 패키지 종속성 아키텍처 테스트

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

둘째 날 ArchUnit 연습: 종속성을 반전한 Layered Architecture 아키텍처 테스트을 다른 테스트 구문을 사용하여 구현합니다.

예 ①: UI 계층 클래스는 인프라 계층 클래스에서만 의존한다.





아키텍처 테스트 구현


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.classes;
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 UI層のクラスはインフラストラクチャ層のクラスからのみ依存される() {
        classes().that().resideInAPackage("com.example.presentation..")
                .should()
                .onlyHaveDependentClassesThat().resideInAPackage(
                    "com.example.infrastructure.."
                )
                .check(CLASSES);
    }
}

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



1일째의 ArchUnit 연습: Layered Architecture 아키텍처 테스트 의 실패 원인과 같이, 어플리케이션 계층의 Service 클래스가, 프레젠테이션 계층의 Helper 클래스에 의존해 버리고 있다, 라고 하는 아키텍쳐 위반을 검지한 가정에서의 테스트 실패 예.
$ ./gradlew clean check

> Task :test

ArchitectureTest > UI層のクラスはインフラストラクチャ層のクラスからのみ依存される() FAILED
    java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'classes that reside in a package 'com.example.presentation..' should only have dependent classes that reside in a package 'com.example.infrastructure..'' 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.lang.ArchRule$Factory$SimpleArchRule.check(ArchRule.java:198)
        at com.tngtech.archunit.lang.syntax.ObjectsShouldInternal.check(ObjectsShouldInternal.java:81)
        at com.example.ArchitectureTest.UI層のクラスはインフラストラクチャ層のクラスからのみ依存される(ArchitectureTest.java:54)

2 tests completed, 1 failed

예 ②: 도메인 계층의 클래스는 다른 계층의 클래스에 의존하지 않는다.





아키텍처 테스트 구현


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.classes;
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 ドメイン層のクラスは他の層のクラスに依存しない() {
        noClasses().that().resideInAPackage("com.example.domain..")
            .should()
            .dependOnClassesThat().resideInAnyPackage(
                "com.example.presentation..",
                "com.example.application..",
                "com.example.infrastructure.."
            )
            .check(CLASSES);
    }
}

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



2일째 ArchUnit 연습: 종속성을 반전한 Layered Architecture 아키텍처 테스트의 실패 원인과 마찬가지로 도메인 계층의 Service 클래스가 인프라 계층의 Repository 클래스에 의존하고 있다는 아키텍처 위반을 감지한 가정에서의 테스트 실패 예.
$ ./gradlew clean check

> Task :test FAILED

ArchitectureTest > ドメイン層のクラスは他の層のクラスに依存しない() FAILED
    java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'no classes that reside in a package 'com.example.domain..' should depend on classes that reside in any package ['com.example.presentation..', 'com.example.application..', 'com.example.infrastructure..']' was violated (2 times):
    Constructor <com.example.domain.employee.EmployeeService.<init>(com.example.infrastructure.datasource.EmployeeRepository)> has parameter of type <com.example.infrastructure.datasource.EmployeeRepository> in (EmployeeService.java:0)
    Field <com.example.domain.employee.EmployeeService.employeeRepository> has type <com.example.infrastructure.datasource.EmployeeRepository> in (EmployeeService.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.lang.ArchRule$Factory$SimpleArchRule.check(ArchRule.java:198)
        at com.tngtech.archunit.lang.syntax.ObjectsShouldInternal.check(ObjectsShouldInternal.java:81)
        at com.example.ArchitectureTest.ドメイン層のクラスは他の層のクラスに依存しない(ArchitectureTest.java:99)

2 tests completed, 1 failed

좋은 웹페이지 즐겨찾기