Building and testing distributed, cloud-native applications remains one of the most persistent challenges for Java developers today. In their joint talk, Mauricio Salatino (Diagrid, CNCF Dapr project) and Laurent Broudoux (Postman, Microcks co-founder) tackled the pain points of testing Spring Boot applications across different environments, showing how modern tools can abstract away infrastructure complexity and enable confidence without the overhead of running full Kubernetes clusters.
The Complexity of Modern Applications
The presenters began with a simple pizza-ordering demo application—three microservices (store, kitchen, delivery) exchanging messages. At first glance, it’s straightforward: Spring Boot with PostgreSQL for persistence, Kafka for messaging, and WebSockets for real-time updates. But as applications evolve, real-world requirements—authentication, caching, distributed configuration, and scaling—quickly complicate the picture.
Running the same application across environments (local, AWS, Kubernetes, managed services) often means swapping dependencies, managing connection pools, and rewriting configuration. For developers, this introduces cognitive load, wasted time troubleshooting, and resource-heavy setups.
Patterns for Managing Drift
The speakers emphasized a key principle: abstract infrastructure complexity behind APIs. Instead of hardcoding dependencies on specific databases, brokers, or cloud services, applications should use consistent APIs that can be reconfigured per environment. This avoids environment drift and allows portability across clusters, clouds, and local development.
Tooling for Developer Experience
The talk focused on three complementary projects:
1. Testcontainers
Testcontainers provides developers with lightweight, disposable instances of infrastructure (databases, message brokers) for local testing. Rather than spinning up entire clusters, developers can run only the components they need for a given service.
2. Dapr
Dapr (Distributed Application Runtime) abstracts common infrastructure capabilities—state stores, pub/sub, secrets, bindings—behind standard APIs. Instead of coding directly against Kafka or PostgreSQL, developers call Dapr APIs, which are implemented via sidecars injected into pods. This enables true portability: the same code can run locally with Testcontainers or in production with cloud-managed services, without modification.
3. Microcks
Microcks simplifies mocking and contract testing. By ingesting specifications (OpenAPI, gRPC, GraphQL, AsyncAPI), it can generate realistic mocks of services for local development and comprehensive test suites for validating conformance. This reduces reliance on brittle mocks or over-provisioned local environments. Importantly, Microcks supports both synchronous APIs and asynchronous event-driven interactions.
Tackling the Testing Burden
The speakers highlighted the cognitive and resource load of distributed testing:
- Cognitive load: remembering endless commands, managing Docker Compose, front-end stacks, or scripts.
- Resource strain: running local clusters consumes CPU and memory unnecessarily.
- Tempting shortcuts: developers often avoid integration tests, overuse mocks, or build biased hand-written stubs—leading to fragile systems.
By relying on contracts as the “source of truth” and offloading complexity to Microcks and Dapr, teams can test against realistic simulations without pulling in every dependent service. This keeps inner-loop development fast, while ensuring conformance and reducing drift.
Contract Testing in Practice
Through live demos, the speakers showed how Microcks can:
- Generate mocks from OpenAPI or AsyncAPI files to simulate missing services.
- Validate that API responses conform to schemas without writing test boilerplate.
- Ensure event-driven systems (Kafka topics wrapped in CloudEvents) respect schemas, serialization, and payload structure.
With this approach, developers can test their slice of the system in isolation, yet with confidence that integration will succeed later.
Key Takeaways
- Abstract complexity with APIs: Use patterns that decouple application logic from infrastructure specifics.
- Leverage sidecars and runtimes: Tools like Dapr shift concerns such as connection pooling, retries, and service discovery out of your code.
- Use contract-based mocks and tests: Microcks turns API specs into reliable mocks and tests, reducing drift and surprises in integration.
- Test locally, confidently: Testcontainers lets you run realistic dependencies without replicating full production clusters.
Distributed applications are inherently complex, and testing them across environments can overwhelm even experienced teams. By combining Testcontainers (for infrastructure emulation), Dapr (for infrastructure abstraction), and Microcks (for contract-based mocking and testing), developers can regain focus on business logic while ensuring consistency from laptop to Kubernetes to cloud.
As the speakers put it: “We’re showing patterns here that apply beyond the tools themselves. The key is reducing scope, abstracting complexity, and testing against contracts so developers can move fast with confidence".