Troubleshooting & FAQ¶
This guide helps you diagnose and resolve common issues when working with Stove.
Common Issues¶
Docker Issues¶
Docker Not Found / Not Running¶
Symptoms:
Solutions:
-
Verify Docker is installed and running:
-
Check Docker daemon status:
-
Restart Docker Desktop (if using Docker Desktop)
-
Check Docker socket permissions:
Docker Image Pull Failures¶
Symptoms:
Solutions:
-
Use a custom registry:
-
Login to registry:
-
Configure per-component registry:
Port Already in Use¶
Symptoms:
Solutions:
-
Find and kill the process using the port:
-
Use a different port:
-
Use dynamic ports: Let the framework assign available ports when possible.
Startup Issues¶
Application Fails to Start¶
Symptoms:
Solutions:
-
Check application logs:
-
Verify configuration is being passed correctly:
-
Ensure your application accepts CLI arguments:
Container Startup Timeout¶
Symptoms:
Solutions:
-
Increase container startup timeout:
-
Check container resource requirements:
- Elasticsearch needs at least 2GB RAM
- Couchbase needs significant memory
-
Reduce memory limits in resource-constrained environments
-
Check Docker resources:
- Increase Docker Desktop memory allocation
- Ensure sufficient disk space
Test Failures¶
Assertion Timeout¶
Symptoms:
Solutions:
-
Increase assertion timeout:
-
Check if the operation actually completes:
- Add logging to verify the operation is triggered
-
Check application logs for errors
-
Verify async processing is working:
Serialization/Deserialization Errors¶
Symptoms:
Solutions:
-
Align ObjectMapper configuration:
val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) registerModule(JavaTimeModule()) disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) } TestSystem() .with { http { HttpClientSystemOptions( contentConverter = JacksonConverter(objectMapper) ) } kafka { KafkaSystemOptions( serde = StoveSerde.jackson.anyByteArraySerde(objectMapper) ) { /* config */ } } } -
Check field name mapping:
-
Verify data class has default constructor for Jackson:
Data Not Found¶
Symptoms:
Solutions:
-
Verify data was actually saved:
-
Check timing - wait for async operations:
-
Verify collection/index names match:
Kafka Message Not Found¶
Symptoms:
Solutions:
-
Verify Kafka interceptor is configured:
-
Check topic names:
-
Verify interceptor class is passed to application:
-
Check consumer group offset configuration:
WireMock Stubs Not Being Hit¶
Symptoms:
Connection refused to external service
Test timeout when calling mocked endpoint
Mock not found / unexpected request
Cause: This is almost always because your application's external service URLs don't match the WireMock URL.
Solutions:
-
Ensure ALL external service URLs point to WireMock:
TestSystem() .with { wiremock { WireMockSystemOptions(port = 9090) } springBoot( runner = { params -> myApp.run(params) }, withParameters = listOf( // ALL external services must use WireMock URL "payment.service.url=http://localhost:9090", "inventory.service.url=http://localhost:9090", "notification.service.url=http://localhost:9090" ) ) } -
Verify your application is reading the URLs from configuration:
-
Check the port matches:
-
Debug by checking WireMock requests:
Memory Issues¶
OutOfMemoryError¶
Symptoms:
Solutions:
-
Increase JVM heap for tests:
-
Limit container memory:
-
Use provided instances instead of containers for CI environments.
CI/CD Issues¶
Docker-in-Docker Not Working¶
Solutions:
-
Use DinD sidecar in CI:
-
Use provided instances:
Slow CI Builds¶
Solutions:
- Use provided instances for external infrastructure
- Enable container reuse:
- Run tests in parallel (ensure proper isolation)
- Use smaller container images when available
Intermittent Failures with Shared Infrastructure¶
Symptoms:
Tests pass locally but fail randomly in CI
Data from another test run appears in assertions
"Topic already exists" or "Index already exists" errors
Tests fail when multiple builds run in parallel
Cause: Multiple test runs are using the same resource names (databases, topics, indices) in shared infrastructure.
Solutions:
-
Use unique resource prefixes per test run:
-
Apply prefixes to all resources:
-
Clean up only your resources:
-
Log the run ID for debugging:
Detailed Guide
See Provided Instances - Test Isolation for comprehensive examples.
FAQ¶
General Questions¶
Q: Can I use Stove with Java?¶
A: Yes, you can use Stove in Java projects! However, the e2e tests themselves need to be written in Kotlin. Stove's DSL is designed specifically for Kotlin, providing a clean and expressive syntax:
class MyE2ETest : FunSpec({
test("should create order") {
TestSystem.validate {
http {
postAndExpectBodilessResponse(
uri = "/orders",
body = Some(CreateOrderRequest()),
expect = { status shouldBe 201 }
)
}
}
}
})
You can still test your Java application with Stove - just write your e2e test files in Kotlin.
Q: Can I use JUnit instead of Kotest?¶
A: Yes, Stove works with both JUnit and Kotest. See the Getting Started guide for JUnit examples.
Q: How do I debug tests?¶
A:
- Set breakpoints in your application code
- Run tests in debug mode
- Use verbose logging:
- Access application beans:
Q: Can I run tests in parallel?¶
A: Yes, but ensure proper test isolation:
- Use unique test data (UUIDs)
- Don't share state between tests
- Be careful with shared resources
Q: How do I test with SSL/TLS?¶
A: Configure the component with security enabled:
elasticsearch {
ElasticsearchSystemOptions(
container = ElasticContainerOptions(
disableSecurity = false
),
configureExposedConfiguration = { cfg ->
// Certificate info available in cfg.certificate
listOf(...)
}
)
}
Component-Specific Questions¶
Q: Why isn't my Kafka message being intercepted?¶
A: Ensure:
TestSystemInterceptoris registered as a beankafka.interceptorClassesis configured correctly- Your Kafka listener container uses the interceptor
// Application configuration
@Bean
fun containerFactory(
interceptor: ConsumerAwareRecordInterceptor<String, String>
): ConcurrentKafkaListenerContainerFactory<String, String> {
return ConcurrentKafkaListenerContainerFactory<String, String>().apply {
setRecordInterceptor(interceptor)
}
}
Q: How do I test multiple databases?¶
A: Add multiple database components:
TestSystem()
.with {
postgresql { PostgresqlOptions(...) }
mongodb { MongodbSystemOptions(...) }
couchbase { CouchbaseSystemOptions(...) }
}
Q: Can I use custom container images?¶
A: Yes:
kafka {
KafkaSystemOptions(
container = KafkaContainerOptions(
registry = "my-registry.com",
image = "custom/kafka",
tag = "3.5.0"
)
) { /* config */ }
}
Q: How do I handle database migrations?¶
A: Use the migrations API:
postgresql {
PostgresqlOptions(...).migrations {
register<CreateUserTableMigration>()
register<CreateOrderTableMigration>()
}
}
Q: Can I access the underlying testcontainer?¶
A: For container operations like pause/unpause:
For the client:
Performance Questions¶
Q: How can I speed up test execution?¶
A:
-
Keep containers running:
-
Use provided instances in CI:
-
Reduce container resource allocation:
-
Run independent tests in parallel
Q: Why is container startup slow?¶
A: Container startup depends on:
- Image pull time (first run)
- Container initialization time
- Health check completion
Solutions:
- Pre-pull images in CI
- Use keepDependenciesRunning() locally
- Increase startup timeout for slow containers
Migration Questions¶
Q: How do I migrate from 0.14.x to 0.15.x?¶
A: See Migration Notes for detailed instructions. Key changes:
StoveSerdereplaces directObjectMapperusage- Configure serde for each component that needs it
Getting Help¶
If you can't find a solution:
- Search existing issues: GitHub Issues
- Check examples: Examples Directory
- Open a new issue: Include:
- Stove version
- JDK version
- Docker version
- Complete error message
- Minimal reproduction code
Debug Checklist¶
When troubleshooting, check these items:
- [ ] Docker is running and accessible
- [ ] Correct Stove version in dependencies
- [ ] Application main function is properly modified
- [ ] Configuration is passed to application
- [ ] Serializers match between Stove and application
- [ ] Container has enough resources
- [ ] Ports are not conflicting
- [ ] Network is accessible (for provided instances)
- [ ] Timeouts are appropriate for your environment