Files
werkbaum/backend/build.gradle.kts
T
mhoennigandClaude Opus 5 b6509ae537 test(backend): Kotest-Assertions statt JUnit, CLAUDE.md berichtigt
backend/CLAUDE.md sah Kotest-Assertions vor, der Code benutzte aber die
JUnit-Assertions. Umgestellt bei 25 Aufrufen in zwei Dateien - jetzt billig,
und Test-Abhaengigkeiten sind unkritisch, weil sie in keinem Artefakt landen.
Wo Kotest spezifischer ist, ersetzt es die handgeschriebenen Meldungen:
shouldContain statt assertTrue(contains, "..."), withClue nur noch dort, wo
der Kontext wirklich hilft.

Gegenprobe per Mutation: eine falsche Erwartung im Service-Test und eine im
BDD-Schritt lassen genau die danach benannten Tests fallen.

CLAUDE.md berichtigt: Das Backend ist nicht mehr "noch nicht bootstrapped",
die Konfiguration heisst application.yaml, die Schichten entsprechen dem
tatsaechlichen Aufbau, und die drei Spring-Boot-4-Fallen von heute sind
festgehalten, damit sie niemanden erneut treffen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:29:24 +02:00

136 lines
4.4 KiB
Kotlin

plugins {
kotlin("jvm") version "2.2.20"
kotlin("plugin.spring") version "2.2.20"
kotlin("plugin.jpa") version "2.2.20"
id("org.springframework.boot") version "4.0.2"
id("io.spring.dependency-management") version "1.1.7"
id("org.openapi.generator") version "7.25.0"
jacoco
}
group = "de.werkbaum"
version = "0.1.0-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
val cucumberVersion = "7.23.0"
val mockkVersion = "1.13.16"
val kotestVersion = "5.9.1"
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
// Boot 4: Liquibase-Autokonfiguration liegt im eigenen Starter (zieht liquibase-core mit)
implementation("org.springframework.boot:spring-boot-starter-liquibase")
runtimeOnly("com.h2database:h2")
implementation("org.jetbrains.kotlin:kotlin-reflect")
// Jackson 3 (Standard in Spring Boot 4) + Kotlin-Modul
implementation("tools.jackson.module:jackson-module-kotlin")
// --- Tests ---
testImplementation("org.springframework.boot:spring-boot-starter-test")
// RestTestClient-Autokonfiguration (Boot 4). TestRestTemplate gilt dort als
// Auslaufmodell; die BDD-Tests nutzen den Nachfolger aus spring-test.
testImplementation("org.springframework.boot:spring-boot-resttestclient")
testImplementation("io.mockk:mockk:$mockkVersion")
// Nur die Assertions - Testrunner bleibt JUnit 5 (backend/CLAUDE.md)
testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
// Behavior-Tests (BDD) mit Cucumber
testImplementation("io.cucumber:cucumber-java:$cucumberVersion")
testImplementation("io.cucumber:cucumber-spring:$cucumberVersion")
testImplementation("io.cucumber:cucumber-junit-platform-engine:$cucumberVersion")
testImplementation("org.junit.platform:junit-platform-suite")
}
// ---------------------------------------------------------------------------
// API First: Code-Generierung aus der OpenAPI-Spezifikation
// ---------------------------------------------------------------------------
openApiGenerate {
generatorName.set("kotlin-spring")
inputSpec.set("$projectDir/src/main/resources/openapi/api.yaml")
outputDir.set(layout.buildDirectory.dir("generated/openapi").get().asFile.path)
apiPackage.set("de.werkbaum.generated.api")
modelPackage.set("de.werkbaum.generated.model")
configOptions.set(
mapOf(
"useSpringBoot4" to "true",
"interfaceOnly" to "true", // nur Interfaces + Modelle, Implementierung liegt bei uns
"skipDefaultInterface" to "true", // Controller MUSS alle Operationen implementieren
"useTags" to "true", // Interface-Name aus Tag: DocumentsApi
"useBeanValidation" to "true",
"documentationProvider" to "none",
"enumPropertyNaming" to "UPPERCASE",
"gradleBuildFile" to "false",
)
)
}
sourceSets {
main {
kotlin {
srcDir(layout.buildDirectory.dir("generated/openapi/src/main/kotlin"))
}
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
dependsOn(tasks.openApiGenerate)
}
// ---------------------------------------------------------------------------
// Tests + Code Coverage
// ---------------------------------------------------------------------------
tasks.test {
useJUnitPlatform()
finalizedBy(tasks.jacocoTestReport)
}
jacoco {
toolVersion = "0.8.13"
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required = true
html.required = true
}
// Generierter Code zaehlt nicht zur Coverage
classDirectories.setFrom(
classDirectories.files.map {
fileTree(it) { exclude("de/werkbaum/generated/**") }
}
)
}
tasks.jacocoTestCoverageVerification {
dependsOn(tasks.test)
classDirectories.setFrom(
classDirectories.files.map {
fileTree(it) { exclude("de/werkbaum/generated/**") }
}
)
violationRules {
rule {
limit {
counter = "LINE"
minimum = "0.80".toBigDecimal()
}
}
}
}
tasks.check {
dependsOn(tasks.jacocoTestCoverageVerification)
}