-
Notifications
You must be signed in to change notification settings - Fork 41.3k
Description
Spring Boot 3.1 introduced support for Testcontainers at development time, which was really a great addition to the framework, so thanks so much for that! I've been using that feature ever since in all my projects that have service dependencies.
I'd like to share some challenges when using this feature and some suggestions for a possible evolution of such a feature, mainly aiming at improving the developer experience, filling a gap with other frameworks.
Developer Experience: Running a Spring Boot application in development
The feature requires a different way to run the application in a development environment (in Gradle, it's bootTestRun
instead of bootRun
), which makes it less straightforward to know how to run a new project. The different command requires inspecting the project before knowing how to run it. When using the IDE instead of the CLI, it also gets less straightforward as both application entry points would be recognised (e.g. MyApplication
and TestMyApplication
), with IDEs usually defaulting on the first one and resulting in a failure (that's what typically happens when using Visual Studio Code). For experienced developers, this creates friction in the usual development workflow. For developers new to Spring Boot, this creates lots of confusion.
It would be great if the command for running an application would not change and be consistent across all Spring Boot projects (in Gradle, bootRun
even when using Testcontainers at development time). And also having one single main entry point (e.g. MyApplication
without a parallel TestMyApplication
in the test classpath) This would mean bringing in the necessary dependencies for test and development only, similar to how Spring Boot DevTools work, instead of having them just in the test classpath.
Developer Experience: Auto-Configuration and Dependency Management
Among the other things, Spring Boot offers convenient dependency management via starter modules and auto-configuration. However, for Testcontainers support at development time, both features are missing. If I have a project with Spring Data JDBC and PostgreSQL, I have to know which dependencies to add to the classpath to get a PostgreSQL Testcontainer up and running (at least 3 extra dependencies are needed).
Furthermore, I need to explicitly define a bean of type PostgreSQLContainer
. That's boilerplate code I need to copy/paste in every project where I'd like to have a PostgreSQL Dev Service. The lack of auto-configuration means I cannot switch on/off a container via properties, but it's up to me to decorate the bean with some profiles or something like that. For example, I might want the Ollama Testcontainers running only in tests by default (since it's less performant than native Ollama). One more consequence of the lack of auto-configuration means I cannot make a container reusable at development time, but not when running integration tests (important for services like message queues and other shared services), forcing me to add more code to support this setup.
It would be great if common Spring Boot features like starter dependencies and auto-configuration would be applied to Testcontainers at development time. The developer experience would be much better if the only thing to do to have a PostgreSQL Dev Service would be to add a single dependency, without any explicit configuration or boilerplate code. Auto-configuration would make it straightforward to customise certain behaviours of the container based on whether it's running in development mode or during an integration test (e.g. whether a container should be shared). For experienced developers, this would make the feature more appealing as it would be in line with other Spring Boot features in terms of reduced boilerplate and streamlined dependency management. For developers new to Spring Boot, it would help them get up and running without exposing them to so much cognitive load from day 1 when running a Spring Boot app with a database for the first time.
Developer Experience: Integration Testing
When running Spring Boot integration tests in a project with Testcontainers configured at development time, I have to include the Testcontainers configuration explicitly in all tests. If more granularity is needed, that would require splitting the configuration in multiple classes or adding several profiles/properties to pick and choose the ones to include. Overall, there's a lot of extra work for running integration tests, work that needs to be repeated in all applications.
It would be great to get the Spring Boot integration tests pick up the already configured Testcontainers at development time, instead of requiring explicit inclusion of the configuration. And thanks to auto-configuration, it would be straightforward to switch on/off a certain container via configuration properties.
Additional Context
I've been investigating options for implementing the solution I suggested. I have a working library as part of my Arconia project to showcase that. See Arconia Dev Services. It's not perfect and still experimental, but it's been helpful for my projects to overcome some of the challenges described above. It's also additive, making it possible to still use the existing support in core Spring Boot (no breaking change). If there's anything useful there that might make sense in the context of the Spring Boot project, I'd be happy to contribute it upstream or help out in any way I can to make this feature happen.
In any case, thank you all for the great work on Spring Boot!