Last active
December 22, 2023 00:31
-
-
Save philipjkim/f1644f7f6acccc5e6264fed7a025f960 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.philipjkim.demo.hexagonal | |
import ch.qos.logback.classic.Level | |
import ch.qos.logback.classic.Logger | |
import com.tngtech.archunit.core.importer.ClassFileImporter | |
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses | |
import org.junit.jupiter.api.Assertions.* | |
import org.junit.jupiter.api.BeforeAll | |
import org.junit.jupiter.api.DisplayName | |
import org.junit.jupiter.api.Nested | |
import org.junit.jupiter.api.Test | |
import org.slf4j.LoggerFactory | |
/* | |
* Layer dependency direction: | |
* external -> adapter -> application -> domain | |
*/ | |
@DisplayName("package dependency rule") | |
internal class DependencyRuleTest { | |
@Nested | |
@DisplayName("for callback domain") | |
inner class ForCallbackDomain { | |
private val basePackage = "com.github.philipjkim.demo.hexagonal.callback" | |
@Test | |
@DisplayName("domain layer should not depend on any of [application, adapter, external] layers.") | |
fun domainLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"domain", | |
listOf("application", "adapter", "external"), | |
) | |
} | |
@Test | |
@DisplayName("application layer should not depend on any of [adapter, external] layers.") | |
fun applicationLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"application", | |
listOf("adapter", "external"), | |
) | |
} | |
@Test | |
@DisplayName("adapter layer should not depend on external layer.") | |
fun adapterLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"adapter", | |
listOf("external"), | |
) | |
} | |
} | |
@Nested | |
@DisplayName("for auth domain") | |
inner class ForAuthDomain { | |
private val basePackage = "com.github.philipjkim.demo.hexagonal.auth" | |
@Test | |
@DisplayName("domain layer should not depend on any of [application, adapter, external] layers.") | |
fun domainLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"domain", | |
listOf("application", "adapter", "external"), | |
) | |
} | |
@Test | |
@DisplayName("application layer should not depend on any of [adapter, external] layers.") | |
fun applicationLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"application", | |
listOf("adapter", "external"), | |
) | |
} | |
@Test | |
@DisplayName("adapter layer should not depend on external layer.") | |
fun adapterLayerDoesNotDependOnOuterLayers() { | |
assertDependencyRulesKeptFor( | |
basePackage, | |
"adapter", | |
listOf("external"), | |
) | |
} | |
} | |
/** | |
* Assert that all classes in `basePackage.innerPackage` | |
* do not depend on any classes in `basePackage.outerPackages`. | |
* | |
* @param basePackage base package of given domain (ex: `com.github.philipjkim.demo.hexagonal.callback`) | |
* @param innerPackage the inner package name which is the object of the test (ex: `domain`) | |
* @param outerPackages outer packages from the inner package (ex: `[application, adapter, external]`) | |
*/ | |
private fun assertDependencyRulesKeptFor( | |
basePackage: String, | |
innerPackage: String, | |
outerPackages: List<String>, | |
) { | |
noClasses() | |
.that() | |
.resideInAPackage("${basePackage}.${innerPackage}..") | |
.should() | |
.dependOnClassesThat() | |
.resideInAnyPackage( | |
*(outerPackages.map { "${basePackage}.${it}.." }.toTypedArray()) | |
) | |
.check(ClassFileImporter().importPackages("${basePackage}..")) | |
} | |
companion object { | |
@JvmStatic | |
@BeforeAll | |
fun setUp() { | |
val rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger | |
rootLogger.level = Level.INFO | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment