0.20.0 (To be released)¶
Release Date: To be released
This release introduces:
- Simplified Module Names: All modules renamed to remove
testing-e2esuffix for cleaner artifact names - New BOM (Bill of Materials): Centralized version management via
stove-bom - Package Structure Simplification: Package names simplified from
com.trendyol.stove.testing.e2e.*tocom.trendyol.stove.* - Test Reporting System: Comprehensive reporting that tracks all actions and assertions during test execution
- Spring Boot 4.x Support: Full support for Spring Boot 4.x and Spring Kafka 4.x
- Unified Spring Modules: Single modules that work across Spring Boot 2.x, 3.x, and 4.x
- New Bean Registration DSL:
stoveSpring4xRegistrarfor Spring Boot 4.x (sinceBeanDefinitionDslis deprecated) - Runtime Version Checks: Clear error messages when Spring Boot/Kafka is missing from classpath
- Ktor DI Flexibility: Support for Koin, Ktor-DI, or custom resolvers
- Generic Type Resolution:
using<List<T>>now works correctly with full generic type preservation
New Features¶
Test Reporting System¶
Stove now includes a built-in reporting system that captures everything that happens during your tests. When a test fails, you get a detailed report showing exactly what happened, making debugging much easier.
Key capabilities:
- Automatic tracking of all system interactions (HTTP, Kafka, database, WireMock, gRPC)
- Test failure enrichment with detailed execution reports embedded in test output
- System snapshots showing internal state (Kafka messages, WireMock stubs) at the time of failure
- Multiple renderers - human-readable console output or machine-readable JSON
- Framework integration with both Kotest and JUnit
- Stack trace preservation - original stack traces are preserved in test failures
Quick Start - Kotest¶
Add the extension dependency (optional but recommended):
Then configure:
import com.trendyol.stove.extensions.kotest.StoveKotestExtension
import com.trendyol.stove.system.Stove
class TestConfig : AbstractProjectConfig() {
override val extensions: List<Extension> = listOf(StoveKotestExtension())
override suspend fun beforeProject() {
Stove()
.with { /* your configuration */ }
.run()
}
override suspend fun afterProject() {
Stove.stop()
}
}
Quick Start - JUnit¶
Add the extension dependency (optional but recommended):
Then configure:
import com.trendyol.stove.extensions.junit.StoveJUnitExtension
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(StoveJUnitExtension::class)
class MyE2ETest {
// your tests
}
The JUnit extension works with both JUnit 5 and 6 since they share the Jupiter API.
Configuration¶
Stove {
reporting {
enabled() // Enable reporting (default: true)
dumpOnFailure() // Dump report when tests fail (default: true)
failureRenderer(PrettyConsoleRenderer) // Set the renderer
}
}
Example Output¶
When a test fails, you'll see output like:
╔══════════════════════════════════════════════════════════════════════════════╗
║ STOVE TEST EXECUTION REPORT ║
║ Test: should save the product ║
║ Status: FAILED ║
╠══════════════════════════════════════════════════════════════════════════════╣
║ 14:47:38.215 ✓ PASSED [HTTP] POST /api/products ║
║ Input: {"id":1234,"name":"Test Product"} ║
║ ║
║ 14:47:38.341 ✗ FAILED [Kafka] shouldBePublished<ProductCreatedEvent> ║
║ Expected: Message matching condition within 5s ║
║ Actual: No matching message found ║
║ Error: GOT A TIMEOUT: While expecting the publish of 'ProductCreatedEvent'║
╠══════════════════════════════════════════════════════════════════════════════╣
║ SYSTEM SNAPSHOTS ║
║ ┌─ KAFKA ────────────────────────────────────────────────────────────────────║
║ Consumed: 0 ║
║ Produced: 1 ║
║ State Details: ║
║ produced: 1 item(s) ║
║ [0] topic: product-events, value: {"id":1234,"name":"Test Product"} ║
╚══════════════════════════════════════════════════════════════════════════════╝
Available Renderers¶
- PrettyConsoleRenderer (default) - Colorized, box-drawing output for terminals
- JsonReportRenderer - Machine-readable JSON for CI/CD integration
See the Reporting documentation for full details.
Spring Boot 4.x Support¶
Stove now fully supports Spring Boot 4.x and Spring Kafka 4.x. The existing stove-spring and stove-spring-kafka modules work with all Spring Boot versions (2.x, 3.x, and 4.x).
Dependencies remain the same:
testImplementation("com.trendyol:stove-spring:0.20.0")
testImplementation("com.trendyol:stove-spring-kafka:0.20.0")
New Bean Registration DSL for Spring Boot 4.x¶
Spring Boot 4.x deprecates BeanDefinitionDsl (beans { } DSL). Stove provides new extension functions for cleaner bean registration:
Spring Boot 2.x / 3.x - use addTestDependencies:
import com.trendyol.stove.addTestDependencies
springBoot(
runner = { params ->
runApplication<MyApp>(args = params) {
addTestDependencies {
bean<TestSystemKafkaInterceptor<*, *>>()
bean<MyService> { MyServiceImpl() }
}
}
}
)
Spring Boot 4.x - use addTestDependencies4x:
import com.trendyol.stove.addTestDependencies4x
springBoot(
runner = { params ->
runApplication<MyApp>(args = params) {
addTestDependencies4x {
registerBean<TestSystemKafkaInterceptor<*, *>>(primary = true)
registerBean<MyService> { MyServiceImpl() }
}
}
}
)
Alternative: Using addInitializers directly:
// Spring Boot 2.x / 3.x
addInitializers(stoveSpringRegistrar { bean<MyService>() })
// Spring Boot 4.x
addInitializers(stoveSpring4xRegistrar { registerBean<MyService>() })
Key differences for 4.x:
- Use registerBean<T>() instead of bean<T>()
- Use registerBean<T>(primary = true) for primary beans
- No ref() function - use constructor injection instead
Ktor DI Flexibility¶
Stove's Ktor module now supports multiple dependency injection systems. Previously, Koin was required. Now you can use:
- Koin (existing support)
- Ktor-DI (new built-in support)
- Custom resolver (any DI framework)
Both Koin and Ktor-DI are now compileOnly dependencies - you bring your preferred DI system.
Using Koin:
dependencies {
testImplementation("io.insert-koin:koin-ktor:$koinVersion")
}
// In your test setup
bridge() // Auto-detects Koin
Using Ktor-DI:
dependencies {
testImplementation("io.ktor:ktor-server-di:$ktorVersion")
}
// In your test setup
bridge() // Auto-detects Ktor-DI
Using a Custom Resolver:
For any other DI framework (Kodein, Dagger, manual, etc.):
bridge { application, type ->
// Your custom resolution logic - type is KType preserving generics
myDiContainer.resolve(type)
}
Generic Type Resolution in Bridge System¶
The using<T> function now properly preserves generic type information, allowing you to resolve types like List<PaymentService>:
// Register multiple implementations
provide<List<PaymentService>> {
listOf(StripePaymentService(), PayPalPaymentService())
}
// Resolve with full generic type preserved
validate {
using<List<PaymentService>> {
forEach { service -> service.pay(order) }
}
}
This works by using KType instead of KClass internally, which preserves generic type parameters that would otherwise be lost due to JVM type erasure.
For custom BridgeSystem implementations: Override getByType(type: KType) to support generic types. The default implementation falls back to get(klass: KClass).
Ktor Test Dependency Registration¶
Unlike Spring Boot's unified addTestDependencies, Ktor test dependency registration differs by DI framework:
Koin:
// In your app - accept test modules
fun run(args: Array<String>, testModules: List<Module> = emptyList()): Application {
return embeddedServer(Netty, port = args.getPort()) {
install(Koin) { modules(appModule, *testModules.toTypedArray()) }
}.start(wait = false).application
}
// In tests - pass test modules with overrides
ktor(runner = { params ->
MyApp.run(params, testModules = listOf(
module {
single<TimeProvider>(override = true) { FixedTimeProvider() }
}
))
})
Ktor-DI:
// In your app - accept test dependencies
fun run(args: Array<String>, testDeps: (DependencyRegistrar.() -> Unit)? = null): Application {
return embeddedServer(Netty, port = args.getPort()) {
install(DI) {
dependencies {
provide<MyService> { MyServiceImpl() }
testDeps?.invoke(this) // Later provides override earlier ones
}
}
}.start(wait = false).application
}
// In tests - pass test overrides
ktor(runner = { params ->
MyApp.run(params) {
provide<TimeProvider> { FixedTimeProvider() }
}
})
Runtime Version Checks¶
When Spring Boot, Spring Kafka, or Ktor DI is missing from the classpath, Stove now provides clear error messages:
═══════════════════════════════════════════════════════════════════════════════
Spring Boot Not Found on Classpath!
═══════════════════════════════════════════════════════════════════════════════
stove-spring requires Spring Boot to be on your classpath.
Spring Boot is declared as a 'compileOnly' dependency, so you must add it
to your project.
Add one of the following to your build.gradle.kts:
For Spring Boot 2.x:
testImplementation("org.springframework.boot:spring-boot-starter:2.7.x")
For Spring Boot 3.x:
testImplementation("org.springframework.boot:spring-boot-starter:3.x.x")
For Spring Boot 4.x:
testImplementation("org.springframework.boot:spring-boot-starter:4.x.x")
═══════════════════════════════════════════════════════════════════════════════
Migration Guide¶
From 0.19.x to 0.20.0¶
This is a breaking change release. Follow these steps to migrate:
1. Update Module Names (Required)¶
See the Breaking Changes - Module and Package Renaming section above for detailed migration steps and regex patterns.
Quick Summary:
- Update all artifact names in build files
- Replace stove-testing-e2e → stove
- Replace stove-*-testing-e2e → stove-*
- Update all package imports from com.trendyol.stove.testing.e2e.* → com.trendyol.stove.*
2. Test Framework Extensions (Optional)¶
Test framework extensions are now in separate modules. They're optional but recommended for better failure reporting. Add the one that matches your test framework:
dependencies {
// For Kotest
testImplementation("com.trendyol:stove-extensions-kotest")
// OR for JUnit 5/6
testImplementation("com.trendyol:stove-extensions-junit")
}
Update your imports:
// Kotest
import com.trendyol.stove.extensions.kotest.StoveKotestExtension
// JUnit
import com.trendyol.stove.extensions.junit.StoveJUnitExtension
3. Use the New BOM (Recommended)¶
The new BOM simplifies version management:
dependencies {
testImplementation(platform("com.trendyol:stove-bom:0.20.0"))
// No versions needed - managed by BOM
testImplementation("com.trendyol:stove")
testImplementation("com.trendyol:stove-spring")
testImplementation("com.trendyol:stove-kafka")
}
From 0.19.x (Other Changes)¶
Test Extensions for Better Reporting¶
The reporting extensions are optional but make debugging much easier. Add the one for your test framework:
Kotest:
// Add dependency: testImplementation("com.trendyol:stove-extensions-kotest")
class TestConfig : AbstractProjectConfig() {
override val extensions = listOf(StoveKotestExtension())
}
JUnit:
For Spring Boot 2.x and 3.x Users¶
If using BaseApplicationContextInitializer: Migrate to addTestDependencies (see Breaking Changes below).
If using beans { } directly: Your existing code continues to work. Optionally, use the new cleaner API:
// Old way (still works)
addInitializers(beans { bean<MyService>() })
// New way (recommended)
addTestDependencies { bean<MyService>() }
For Spring Boot 4.x Users (New!)¶
Spring Boot 4.x is newly supported in this release. Use addTestDependencies4x:
import com.trendyol.stove.addTestDependencies4x
springBoot(
runner = { params ->
runApplication<MyApp>(args = params) {
addTestDependencies4x {
registerBean<TestSystemKafkaInterceptor<*, *>>(primary = true)
registerBean<MyService> { MyServiceImpl() }
}
}
}
)
Note: The beans { } DSL from Spring is deprecated in 4.x, which is why Stove provides addTestDependencies4x with registerBean<T>().
Breaking Changes¶
Module and Package Renaming¶
⚠️ BREAKING: All Stove modules have been renamed to simplify artifact names and package structure. This is a breaking change that requires updates to your build files and source code.
Module Name Changes¶
| Old Artifact Name | New Artifact Name |
|---|---|
stove-testing-e2e |
stove |
stove-testing-e2e-kafka |
stove-kafka |
stove-testing-e2e-http |
stove-http |
stove-testing-e2e-couchbase |
stove-couchbase |
stove-testing-e2e-elasticsearch |
stove-elasticsearch |
stove-testing-e2e-grpc |
stove-grpc |
stove-testing-e2e-mongodb |
stove-mongodb |
stove-testing-e2e-redis |
stove-redis |
stove-testing-e2e-wiremock |
stove-wiremock |
stove-testing-e2e-rdbms-postgres |
stove-postgres |
stove-testing-e2e-rdbms-mssql |
stove-mssql |
stove-spring-testing-e2e |
stove-spring |
stove-spring-testing-e2e-kafka |
stove-spring-kafka |
stove-ktor-testing-e2e |
stove-ktor |
stove-micronaut-testing-e2e |
stove-micronaut |
Package Name Changes¶
All packages have been simplified:
- com.trendyol.stove.testing.e2e.* → com.trendyol.stove.*
- com.trendyol.stove.testing.e2e.rdbms.postgres → com.trendyol.stove.postgres
- com.trendyol.stove.testing.e2e.rdbms.mssql → com.trendyol.stove.mssql
- com.trendyol.stove.testing.e2e.standalone.kafka → com.trendyol.stove.kafka
Migration Guide¶
Step 1: Update Build Files (Gradle/Maven)
Recommended: Use the new BOM for version management:
// build.gradle.kts
dependencies {
// Import BOM
testImplementation(platform("com.trendyol:stove-bom:$version"))
// Core and framework (no version needed - managed by BOM)
testImplementation("com.trendyol:stove")
testImplementation("com.trendyol:stove-spring") // or stove-ktor, stove-micronaut
// Components (no version needed)
testImplementation("com.trendyol:stove-kafka")
testImplementation("com.trendyol:stove-postgres")
// ... other components
}
Or without BOM (specify versions explicitly):
dependencies {
testImplementation("com.trendyol:stove:$version")
testImplementation("com.trendyol:stove-spring:$version")
testImplementation("com.trendyol:stove-kafka:$version")
testImplementation("com.trendyol:stove-postgres:$version")
}
Step 2: Update Package Imports in Source Code
All import statements need to be updated. Use the regex patterns below for automated migration.
Step 3: Automated Migration with Regex
Use these regex patterns in your IDE's find-and-replace (with regex enabled):
For Build Files (Gradle/Maven):
-
Replace artifact names in dependencies:
-
Replace component artifacts:
-
Replace RDBMS artifacts:
-
Replace starter artifacts:
For Source Code (Kotlin/Java):
-
Replace package imports:
-
Replace fully qualified names:
-
Replace standalone.kafka:
-
Replace remaining testing.e2e references:
Step 4: Manual Verification
After automated replacement, verify:
- Build files compile - Run
./gradlew buildormvn compile - Imports resolve - Check that all imports are valid
- Tests compile - Run
./gradlew compileTestKotlinormvn test-compile - Tests pass - Run your test suite
Example Migration
Before (0.19.0):
// build.gradle.kts
dependencies {
testImplementation("com.trendyol:stove-testing-e2e:0.19.0")
testImplementation("com.trendyol:stove-spring-testing-e2e:0.19.0")
testImplementation("com.trendyol:stove-testing-e2e-kafka:0.19.0")
testImplementation("com.trendyol:stove-testing-e2e-rdbms-postgres:0.19.0")
}
// Test code
import com.trendyol.stove.testing.e2e.system.TestSystem
import com.trendyol.stove.testing.e2e.kafka.kafka
import com.trendyol.stove.testing.e2e.rdbms.postgres.postgresql
After (0.20.0):
// build.gradle.kts
dependencies {
testImplementation(platform("com.trendyol:stove-bom:0.20.0"))
testImplementation("com.trendyol:stove")
testImplementation("com.trendyol:stove-spring")
testImplementation("com.trendyol:stove-kafka")
testImplementation("com.trendyol:stove-postgres")
}
// Test code
import com.trendyol.stove.system.TestSystem
import com.trendyol.stove.kafka.kafka
import com.trendyol.stove.postgres.postgresql
Migration Checklist
- [ ] Update all
build.gradle.kts/build.gradle/pom.xmlfiles - [ ] Replace all import statements in test source code
- [ ] Replace all fully qualified package references
- [ ] Update any documentation or scripts referencing old artifact names
- [ ] Verify build compiles successfully
- [ ] Run test suite to ensure everything works
Need Help?
If you encounter issues during migration: 1. Check the Migration Guide section below 2. Review the Getting Started guide for updated examples 3. Open an issue on GitHub
BaseApplicationContextInitializer Removed¶
BaseApplicationContextInitializer has been removed. Migrate to addTestDependencies:
Before (0.19.0):
class TestSystemInitializer : BaseApplicationContextInitializer({
bean<TestSystemKafkaInterceptor<*, *>>()
bean<MyService> { MyServiceImpl() }
})
// Usage
runApplication<MyApp>(args = params) {
addInitializers(TestSystemInitializer())
}
After (0.20.0):
import com.trendyol.stove.addTestDependencies
runApplication<MyApp>(args = params) {
addTestDependencies {
bean<TestSystemKafkaInterceptor<*, *>>()
bean<MyService> { MyServiceImpl() }
}
}
This is simpler - no need to create a separate class.
HttpSystem: getResponse renamed to getResponseBodiless¶
The getResponse method in HttpSystem has been renamed to getResponseBodiless to better reflect its purpose - it returns a response without parsing the body.
Before:
After:
Notes¶
BridgeSystem API Enhancement¶
The BridgeSystem abstract class now has a new method getByType(type: KType) which is used by resolve() to support generic types. If you have a custom BridgeSystem implementation:
- No action required if you only use simple types - the default implementation falls back to
get(klass: KClass) - Override
getByType(type: KType)if you want to support generic types likeList<T>,Map<K,V>, etc.
// Example for custom bridge
override fun <D : Any> getByType(type: KType): D {
// Use type.classifier for KClass
// Use type.arguments for generic parameters
return myDiFramework.resolve(type)
}
Dead Letter Topic Naming Convention (Spring Kafka)¶
Be aware that Spring Kafka changed the default DLT (Dead Letter Topic) naming convention between versions:
| Spring Kafka Version | DLT Suffix | Example |
|---|---|---|
| 2.x | .DLT |
my-topic.DLT |
| 3.x, 4.x | -dlt |
my-topic-dlt |
This is not a Stove change, but something to be aware of when writing Kafka tests across different Spring Kafka versions.
Optional: Disable Reporting¶
If you don't want the new reporting feature (not recommended), you can disable it:
Dependency Updates¶
- Spring Boot 4.x support (4.0.0+)
- Spring Kafka 4.x support (4.0.0+)
- Continued support for Spring Boot 2.7.x and 3.x
- Continued support for Spring Kafka 2.9.x and 3.x
Full Changelog¶
See the GitHub Releases page for the complete list of commits and contributors.
Contributors¶
Thanks to all contributors who made this release possible!
Getting Started¶
dependencies {
testImplementation("com.trendyol:stove:0.20.0")
testImplementation("com.trendyol:stove-spring:0.20.0")
// Add component-specific dependencies as needed
testImplementation("com.trendyol:stove-spring-kafka:0.20.0")
}
For snapshot versions, add the snapshot repository: