Skip to content

Instantly share code, notes, and snippets.

@ndemengel
Last active January 17, 2021 15:57
Show Gist options
  • Save ndemengel/5750cf44ccdc1704a6fb5851d1134a6b to your computer and use it in GitHub Desktop.
Save ndemengel/5750cf44ccdc1704a6fb5851d1134a6b to your computer and use it in GitHub Desktop.
Enforcing dependency rules between Maven modules using JUnit
package com.malt.architecture.libfreelancer
import com.malt.architecture.shouldNotDependOnModulesOfOtherGroups
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
@Tag("lib-freelancer")
internal class CheckFreelancerLibsDependenciesTest {
@Test
fun `should not depend on modules from higher groups`() {
shouldNotDependOnModulesOfOtherGroups(
groupToCheck = "lib-freelancer",
groupsAuthorizedAsDependencies = setOf(
"tech-starters",
"lib-platform",
"lib-shared-domains",
"lib-to-be-sorted-out",
"lib-freelancer"
)
)
}
}
package com.malt.architecture
import org.apache.maven.model.Model
import org.apache.maven.model.io.xpp3.MavenXpp3Reader
import org.assertj.core.api.SoftAssertions
import java.io.FileReader
import java.nio.file.Path
private val ourGroupIds = listOf("com.hopwork", "com.malt")
// Needed resources are searched starting from the current source file. This allows for launching
// tests from any directory, which is especially useful when run from an IDE.
private val testClassesDir = Path.of(::shouldNotDependOnModulesOfOtherGroups.javaClass.classLoader.getResource(".")?.path)
private val targetDir = testClassesDir.parent
private val archChecksModuleDir = targetDir.parent
private val repoDir = archChecksModuleDir.parent
fun shouldNotDependOnModulesOfOtherGroups(
groupToCheck: String,
groupsAuthorizedAsDependencies: Set<String>,
exceptions: Set<String> = emptySet()
) {
val dirOfGroupToCheck = repoDir.resolve(groupToCheck)
val modulesOfGroupToCheck = readPom(dirOfGroupToCheck).modules
val artifactIdsOfAuthorizedDependencies = groupsAuthorizedAsDependencies.asSequence()
.map { readPom(repoDir.resolve(it)) }
.flatMap { it.modules }
.toSet()
val softly = SoftAssertions()
modulesOfGroupToCheck.forEach { module ->
val modulePom = readPom(dirOfGroupToCheck.resolve(module))
val dependenciesOfOurs = modulePom.dependencies
.filter { ourGroupIds.contains(it.groupId) }
val unwantedDependencies = dependenciesOfOurs
.map { it.artifactId }
.filter { !artifactIdsOfAuthorizedDependencies.contains(it) }
.filter { !exceptions.contains(it) }
if (unwantedDependencies.isNotEmpty()) {
softly.fail("Unauthorized dependencies found for ${modulePom.artifactId}: $unwantedDependencies")
}
}
softly.assertAll()
}
private fun readPom(moduleDir: Path): Model {
return MavenXpp3Reader().read(FileReader(moduleDir.resolve("pom.xml").toFile()))
}
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<groupId>com.malt</groupId>
<artifactId>arch-checks</artifactId>
<!-- ... -->
<dependencies>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.16.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.6.3</version>
<scope>test</scope>
</dependency>
<!-- ... -->
</dependencies>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment