애플리케이션의 아키텍처를 테스트 할 수 있는 오픈 소스 라이브러리
패키지 / 클래스 / 레이어 / 슬라이스간의 의존성을 확인하는 기능 제공
최대한 상호 참조(Circular Dependency) 가 없도록 해야하며, 이를 찾아내기 위해 사용 가능
ArchUnit 사용 예시
위 사용 예시를 테스트하기 위해서 일정한 룰을 만들어서 확인할 수 있다!
Maven 기준 pom.xml에 아래의 dependency만 추가하면 끝!
<JUnit5용 ArchUnit>
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5-engine</artifactId>
<version>0.12.0</version>
<scope>test</scope>
</dependency>
아래 코드 예시를 보면서 사용법을 알아 봅시다.
1~3 순서로 진행하면 됩니다
@Test
public void Services_should_only_be_accessed_by_Controllers() {
//1. 특정 패키지에 해당하는 클래스를(바이트 코드를 통해) 읽고
JavaClasses importedClasses = new ClassFileImporter().importPackages("com.example.demo");
//2. 확인할 규칙을 정의하고
ArchRule myRule = classes()
.that().resideInAPackage("..service..")
.should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");
//3. 읽어들인 클래스들이 정한 규칙을 따르는지 확인하기
myRule.check(importedClasses);
}
추가 정보!
JUnit 5 확장팩을 이용해서 ArchUnit 사용하기
@AnalyzeClasses : 클래스를 읽어들여서 확인할 패키지 설정
위 사용법의 1번에 해당
@ArchTest : 확인할 규칙 정의
위 사용법의 2번에 해당
ArchUnit를 이용해서 패키지 의존성 확인
패키지 의존성을 확인하기 위해서 ArchUnit을 사용해 코드를 작성하면 된다.
@Test
void packageDependencyTests() {
JavaClasses classes = new ClassFileImporter().importPackages("com.example.testpractice");
ArchRule userPackageRule = classes().that().resideInAPackage("..user..")
.should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage("..post..", "..comment..");
userPackageRule.check(classes);
}
JUnit5 확장팩을 사용해서 패키지 의존성 확인
확장팩 사용을 하기 위해서는 아래의 두 어노테이션을 사용한다
위 1번에서 사용한 코드를 어노테이션을 이용해서 더욱 간결하게 표현하고 테스트 할 수 있다
@AnalyzeClasses(packagesOf = App.class)
public class ArchTests {
@ArchTest
ArchRule domainPackageRule = classes().that().resideInAPackage("..domain..")
.should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage("..study..", "..member..", "..domain..");
@ArchTest
ArchRule memberPackageRule = noClasses().that().resideInAPackage("..domain..")
.should().accessClassesThat().resideInAPackage("..member..");
@ArchTest
ArchRule studyPackageRule = noClasses().that().resideOutsideOfPackage("..study..")
.should().accessClassesThat().resideInAnyPackage("..study..");
@ArchTest
ArchRule freeOfCycles = slices().matching("..inflearnthejavatest.(*)..")
.should().beFreeOfCycles();
}