Skip to content

Components

Stove uses a pluggable architecture—each physical dependency is a separate module you can add based on what you need. 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
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

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:

  1. Configuration - Define how the component should be set up
  2. Container/Runtime - Manages the testcontainer or provided instance
  3. DSL - Fluent API for test assertions
  4. Cleanup - Automatic resource management
Stove()
  .with {
    // Each component is configured in the `with` block
    kafka { KafkaSystemOptions(...) }
    couchbase { CouchbaseSystemOptions(...) }
    http { HttpClientSystemOptions(...) }
    wiremock { WireMockSystemOptions(...) }

    // 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, 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

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

  1. Use random data - Generate unique identifiers for each test to avoid conflicts
  2. Leverage cleanup functions - Clean test data between runs
  3. Configure timeouts appropriately - Set realistic timeouts for your environment
  4. Use the DSL consistently - Leverage the fluent API for readable tests
  5. 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