From 19a4d610b5ffa2363e652acdbac1949e6c5d6bec Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 06:26:04 +0000 Subject: [PATCH] =?UTF-8?q?TA=20=EC=97=AD=ED=95=A0=20Spring=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=84=20smoke=20(role-ta-live-1522-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../architecture/LayerBoundaryTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/test/java/com/runtimematrix/architecture/LayerBoundaryTest.java diff --git a/src/test/java/com/runtimematrix/architecture/LayerBoundaryTest.java b/src/test/java/com/runtimematrix/architecture/LayerBoundaryTest.java new file mode 100644 index 0000000..30e6a84 --- /dev/null +++ b/src/test/java/com/runtimematrix/architecture/LayerBoundaryTest.java @@ -0,0 +1,62 @@ +package com.runtimematrix.architecture; + +import com.tngtech.archunit.core.domain.JavaClasses; +import com.tngtech.archunit.core.importer.ClassFileImporter; +import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.library.Architectures.layeredArchitecture; +import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static com.tngtech.archunit.library.DependencyRules.NO_CLASSES_DEPEND_ON_UPPER_LAYERS; + +/** ADR-001 레이어 경계 Arquillian 테스트 */ +@DisplayName("아키텍처 경계 검증") +class LayerBoundaryTest { + + private JavaClasses classes; + + @BeforeEach + void setUp() { + classes = new ClassFileImporter().importPackages("com.runtimematrix"); + } + + @Test + @DisplayName("Controller는 Service에만 접근 가능") + void controller_should_only_access_service() { + ArchRule rule = layeredArchitecture() + .layer("Controller").definedBy("..controller..") + .layer("Service").definedBy("..service..") + .layer("Repository").definedBy("..repository..") + .layer("Domain").definedBy("..domain..") + .whereLayer("Controller").mayOnlyAccessLayers("Service", "Domain"); + rule.check(classes); + } + + @Test + @DisplayName("Service는 Repository와 Domain에만 접근 가능") + void service_should_only_access_repository_and_domain() { + ArchRule rule = layeredArchitecture() + .layer("Controller").definedBy("..controller..") + .layer("Service").definedBy("..service..") + .layer("Repository").definedBy("..repository..") + .layer("Domain").definedBy("..domain..") + .whereLayer("Service").mayOnlyAccessLayers("Repository", "Domain"); + rule.check(classes); + } + + @Test + @DisplayName("하위 레이어는 상위 레이어에 의존하지 않음") + void no_upward_dependencies() { + NO_CLASSES_DEPEND_ON_UPPER_LAYERS.check(classes); + } + + @Test + @DisplayName("패키지 간 순환 의존성 없음") + void no_cyclic_dependencies() { + ArchRule rule = SlicesRuleDefinition.slices() + .matching("com.runtimematrix.(*)..").should().beFreeOfCycles(); + rule.check(classes); + } +}