Skip to content

0.19.0

Release Date: December 2025

This release introduces:

  • gRPC System: New component for testing gRPC APIs (grpc-kotlin, Wire)
  • WebSocket Testing: Added to HTTP system for real-time communication testing
  • Partial Mocking: WireMock now supports mockPostContaining, mockPutContaining, mockPatchContaining
  • Embedded Kafka: Run Kafka tests without Docker using useEmbeddedKafka = true
  • Provided Instances: PostgreSQL, MSSQL, MongoDB, Couchbase, Elasticsearch, Redis, and Kafka support connecting to external infrastructure
  • Pause/Unpause: PostgreSQL, MSSQL, MongoDB, Couchbase, Elasticsearch, Redis, and Kafka support container pause/unpause for resilience testing
  • Response Headers: WireMock mocks now support custom response headers

New Features

gRPC Support

Stove now supports testing gRPC APIs with a fluent DSL. The new grpc system works with multiple gRPC providers including grpc-kotlin, Wire, and standard gRPC stubs.

// Using typed channels (grpc-kotlin, Wire stubs)
grpc {
    channel<GreeterServiceStub> {
        val response = sayHello(HelloRequest(name = "World"))
        response.message shouldBe "Hello, World!"
    }
}

// Using Wire clients
grpc {
    wireClient<GreeterServiceClient> {
        val response = SayHello().execute(HelloRequest(name = "World"))
        response.message shouldBe "Hello, World!"
    }
}

All streaming types work naturally with Kotlin coroutines:

grpc {
    channel<StreamServiceStub> {
        // Server streaming
        serverStream(request).collect { response ->
            // assertions on each response
        }

        // Client streaming
        val response = clientStream(flow { emit(request1); emit(request2) })

        // Bidirectional streaming
        bidiStream(requestFlow).collect { response ->
            // assertions
        }
    }
}

Add the dependency:

testImplementation("com.trendyol:stove-testing-e2e-grpc:$version")

WebSocket Testing

The HTTP system now supports WebSocket connections for testing real-time communication:

http {
    webSocket("/chat") { session ->
        session.send("Hello!")
        val response = session.receiveText()
        response shouldBe "Echo: Hello!"
    }
}

// With authentication
http {
    webSocket(
        uri = "/secure-chat",
        headers = mapOf("X-Custom-Header" to "value"),
        token = "jwt-token".some()
    ) { session ->
        session.send("Authenticated message")
    }
}

// Collect multiple messages
http {
    webSocketExpect("/notifications") { session ->
        val messages = session.collectTexts(count = 3)
        messages.size shouldBe 3
    }
}

Available methods: - webSocket - Establish connection and interact - webSocketExpect - Assertion-focused testing - webSocketRaw - Direct access to underlying Ktor session


Partial Mocking for WireMock

New partial matching methods allow mocking requests by matching only specific fields in the request body:

wiremock {
    // Match requests containing specific fields (ignores extra fields)
    mockPostContaining(
        url = "/api/orders",
        requestContaining = mapOf(
            "productId" to 123,
            "order.customer.id" to "cust-456"  // Dot notation for nested fields
        ),
        statusCode = 201,
        responseBody = OrderResponse(id = "order-1").some()
    )
}

Features: - AND logic: All specified fields must match - Dot notation: Access nested fields like "order.customer.id" - Partial objects: Nested objects match if they contain at least the specified fields - Methods: mockPostContaining, mockPutContaining, mockPatchContaining


Embedded Kafka Mode

Run Kafka tests without Docker containers using embedded Kafka:

kafka {
    KafkaSystemOptions(
        useEmbeddedKafka = true,  // No container needed
        configureExposedConfiguration = { cfg ->
            listOf("kafka.bootstrapServers=${cfg.bootstrapServers}")
        }
    )
}

This is ideal for: - Self-contained integration tests - Faster test startup - Environments without Docker access


Improvements

Provided Instances (Testcontainer-less Mode)

The following components now support connecting to externally managed infrastructure using the provided() companion function:

Component Provided Instance Support
PostgreSQL
MSSQL
MongoDB
Couchbase
Elasticsearch
Redis
Kafka

PostgreSQL example:

postgresql {
    PostgresqlOptions.provided(
        host = "external-db.example.com",
        port = 5432,
        databaseName = "testdb",
        username = "user",
        password = "pass",
        runMigrations = true,
        cleanup = { client -> client.execute("TRUNCATE users") },
        configureExposedConfiguration = { cfg ->
            listOf("spring.datasource.url=${cfg.jdbcUrl}")
        }
    )
}

Kafka example:

kafka {
    KafkaSystemOptions.provided(
        bootstrapServers = "kafka.example.com:9092",
        runMigrations = true,
        cleanup = { admin -> admin.deleteTopics(listOf("orders")) },
        configureExposedConfiguration = { cfg ->
            listOf("kafka.bootstrapServers=${cfg.bootstrapServers}")
        }
    )
}

This is useful for: - CI/CD pipelines with shared infrastructure - Reducing startup time by reusing existing instances - Lower memory/CPU usage by avoiding container overhead


Pause/Unpause Containers

PostgreSQL, MSSQL, MongoDB, Couchbase, Elasticsearch, Redis, and Kafka now support pausing and unpausing containers for testing resilience scenarios:

postgresql {
    // Pause to simulate network issues
    pause()

    // Your application should handle the connection failure
    http { get<Response>("/health") { it.status shouldBe 503 } }

    // Unpause to restore connectivity
    unpause()
}

Response Headers in WireMock

WireMock now supports custom response headers:

wiremock {
    mockGet(
        url = "/api/users/123",
        statusCode = 200,
        responseBody = user.some(),
        responseHeaders = mapOf(
            "X-Request-Id" to "req-123",
            "X-Rate-Limit-Remaining" to "99"
        )
    )
}

Documentation Improvements

  • Comprehensive documentation for all components
  • Updated examples matching actual API signatures
  • Added component feature matrix showing migration, cleanup, and provided instance support
  • FAQ section with common questions and answers

Dependency Updates

  • Kotlin 2.0.x
  • Kotest 6.0.0.Mx
  • Koin 4.x
  • Arrow 2.x
  • Testcontainers 2.x
  • Ktor 3.x
  • Various other dependency updates for security and compatibility

Migration Guide

From 0.18.x

This release is backward compatible. New features are opt-in:

Feature How to Enable
gRPC testing Add stove-testing-e2e-grpc dependency
WebSocket testing Use http { webSocket("/path") { ... } }
Embedded Kafka Set useEmbeddedKafka = true in KafkaSystemOptions
Provided instances Use SystemOptions.provided(...) instead of SystemOptions(...)
Pause/Unpause Call system.pause() and system.unpause() on container-based systems
Partial WireMock mocking Use mockPostContaining, mockPutContaining, mockPatchContaining
Response headers Pass responseHeaders = mapOf(...) to WireMock mock methods

Breaking Changes

None in this release.


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-testing-e2e:0.19.0")
    testImplementation("com.trendyol:stove-spring-testing-e2e:0.19.0")  // or ktor, micronaut
    // Add component-specific dependencies as needed
    testImplementation("com.trendyol:stove-testing-e2e-rdbms-postgres:0.19.0")
    testImplementation("com.trendyol:stove-testing-e2e-kafka:0.19.0")
    testImplementation("com.trendyol:stove-testing-e2e-grpc:0.19.0")  // NEW
}

For snapshot versions, add the snapshot repository:

repositories {
    maven("https://central.sonatype.com/repository/maven-snapshots")
}