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:
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: