Components¶
Stove uses a pluggable architecture—each physical dependency is a separate module you can add based on what you need. Components use Testcontainers under the hood. All components work together seamlessly, so you can build your test environment to match your production setup.
Available Components¶
| Component | Module | Description |
|---|---|---|
| Kafka | stove-kafka |
Message broker for event-driven architectures |
| Couchbase | stove-couchbase |
NoSQL document database |
| Elasticsearch | stove-elasticsearch |
Search and analytics engine |
| PostgreSQL | stove-postgres |
Relational database |
| MySQL | stove-mysql |
Relational database |
| MongoDB | stove-mongodb |
NoSQL document database |
| MSSQL | stove-mssql |
Microsoft SQL Server |
| Redis | stove-redis |
In-memory data store |
| WireMock | stove-wiremock |
HTTP mock server for external services |
| gRPC Mock | stove-grpc-mock |
gRPC mock server for external gRPC services |
| HTTP Client | stove-http |
HTTP client for testing your API |
| gRPC | stove-grpc |
gRPC client for testing gRPC services |
| Bridge | Built-in | Access to application's DI container |
| Tracing | stove-tracing |
Execution tracing with OpenTelemetry for failure diagnostics |
Quick Start¶
Add the components you need to your build.gradle.kts:
dependencies {
// Import BOM for version management
testImplementation(platform("com.trendyol:stove-bom:$version"))
// Core testing framework
testImplementation("com.trendyol:stove")
// Application framework support
testImplementation("com.trendyol:stove-spring")
// or
testImplementation("com.trendyol:stove-ktor")
// Add components based on your needs
testImplementation("com.trendyol:stove-kafka")
testImplementation("com.trendyol:stove-couchbase")
testImplementation("com.trendyol:stove-elasticsearch")
testImplementation("com.trendyol:stove-http")
testImplementation("com.trendyol:stove-wiremock")
// ... add more as needed
}
Architecture Overview¶
Each component follows a consistent pattern:
- Configuration - Define how the component should be set up
- Container/Runtime - Manages the testcontainer or provided instance
- DSL - Fluent API for test assertions
- Cleanup - Automatic resource management
Stove()
.with {
// Each component is configured in the `with` block
kafka { KafkaSystemOptions(...) }
couchbase { CouchbaseSystemOptions(...) }
http { HttpClientSystemOptions(...) }
wiremock { WireMockSystemOptions(...) }
tracing { enableSpanReceiver() }
// Application under test
springBoot(runner = { params -> myApp.run(params) })
}
.run() // Starts all components and the application
// Test your application
stove {
http { /* HTTP assertions */ }
kafka { /* Kafka assertions */ }
couchbase { /* Database assertions */ }
}
Component Categories¶
Databases¶
| Type | Components | Use Case |
|---|---|---|
| Document | Couchbase, MongoDB, Elasticsearch | JSON document storage, search |
| Relational | PostgreSQL, MySQL, MSSQL | Structured data, transactions |
| Key-Value | Redis | Caching, sessions, pub/sub |
Messaging¶
| Component | Use Case |
|---|---|
| Kafka | Event streaming, message queues, pub/sub |
Network¶
| Component | Use Case |
|---|---|
| HTTP Client | Testing your application's REST API |
| gRPC | Testing your application's gRPC services |
| WireMock | Mocking external HTTP services |
| gRPC Mock | Mocking external gRPC services |
Application Integration¶
| Component | Use Case |
|---|---|
| Bridge | Access application beans and services directly |
| Reporting | Detailed execution reports and failure diagnostics |
| Tracing | Execution tracing with full call chain visibility on failure |
Common Configuration Pattern¶
All components follow a similar configuration pattern:
componentName {
ComponentSystemOptions(
// Container configuration
container = ContainerOptions(
registry = "docker.io",
image = "component-image",
tag = "version"
),
// Expose configuration to your application
configureExposedConfiguration = { cfg ->
listOf(
"app.component.host=${cfg.host}",
"app.component.port=${cfg.port}"
)
}
)
}
Testcontainer vs Provided Instance¶
Each component supports two modes:
Container Mode (Default)¶
Stove automatically manages testcontainers:
kafka {
KafkaSystemOptions(
container = KafkaContainerOptions(tag = "latest"),
configureExposedConfiguration = { cfg -> listOf(...) }
)
}
Provided Instance Mode¶
Connect to existing infrastructure (useful for CI/CD):
kafka {
KafkaSystemOptions.provided(
bootstrapServers = "localhost:9092",
configureExposedConfiguration = { cfg ->
listOf("kafka.bootstrapServers=${cfg.bootstrapServers}")
}
)
}
See Provided Instances for detailed documentation.
Migrations Support¶
Database components support migrations:
class CreateTableseMigration : DatabaseMigration<PostgresSqlMigrationContext> {
override val order: Int = 1
override suspend fun execute(connection: PostgresSqlMigrationContext) {
connection.operations.execute("CREATE TABLE ...")
}
}
postgresql {
PostgresqlOptions(...).migrations {
register<CreateTablesMigration>()
}
}
Cleanup Support¶
All components support cleanup functions for data isolation:
couchbase(
cleanup = { cluster ->
cluster.query("DELETE FROM `bucket` WHERE type = 'test'")
}
) {
CouchbaseSystemOptions(...)
}
Best Practices¶
- Use random data - Generate unique identifiers for each test to avoid conflicts
- Leverage cleanup functions - Clean test data between runs
- Configure timeouts appropriately - Set realistic timeouts for your environment
- Use the DSL consistently - Leverage the fluent API for readable tests
- Combine components - Test complete workflows across multiple systems
Example: Full Stack Test¶
test("should process order end-to-end") {
stove {
val orderId = UUID.randomUUID().toString()
// Mock payment service
wiremock {
mockPost("/payments", statusCode = 200, responseBody = PaymentResult(success = true).some())
}
// Create order via API
http {
postAndExpectBody<OrderResponse>("/orders", body = CreateOrderRequest(orderId).some()) {
it.status shouldBe 201
}
}
// Verify stored in database
couchbase {
shouldGet<Order>("orders", orderId) { order ->
order.status shouldBe "CREATED"
}
}
// Verify event published
kafka {
shouldBePublished<OrderCreatedEvent> { actual.orderId == orderId }
}
// Verify indexed for search
elasticsearch {
shouldGet<Order>(index = "orders", key = orderId) { it.status shouldBe "CREATED" }
}
// Verify cached
redis {
client().connect().sync().get("order:$orderId") shouldNotBe null
}
}
}
Detailed Documentation¶
- Couchbase - NoSQL document database with N1QL queries
- Kafka - Message streaming with producer/consumer testing
- Elasticsearch - Search engine with query DSL support
- WireMock - Mock external HTTP dependencies
- gRPC Mock - Mock external gRPC services
- HTTP Client - Test your REST API endpoints
- gRPC - Test your gRPC services with Wire and grpc-kotlin
- PostgreSQL - Relational database with SQL support
- MongoDB - Document database with aggregation support
- MSSQL - Microsoft SQL Server support
- Redis - In-memory data store for caching
- Bridge - Direct access to application beans
- Provided Instances - Use external infrastructure
- Reporting - Detailed execution reports and failure diagnostics
- Tracing - Execution tracing with OpenTelemetry for full call chain visibility