Reputation: 2663
I am testing a Spring Boot application and trying out Testcontainers to spin up a temporary database in a Docker container for JUnit 5 tests. There are two ways to tell Testcontainers to launch and connect to a test database container:
By defining the container in the test class, adding at least a couple of annotations, and (in a Spring Boot test) also overriding the application context with several lines of code to point it at the fresh database. This is quite a few lines of extra code for each test class.
By setting the spring.datasource.url
property to a specially modified URL. The most elegant approach, though arguably a drawback is that this makes the tests less explicit about what's going on.
I'd like to use option #2, but the limitation (I think) is that it requires you to go with a standard (empty) "library" image of PostgreSQL (or whatever database). I have a custom database image, with a Dockerfile of its own. In particular this image contains a number of initalization scripts (not just one) to build up the database schema.
Is there any way to use the JDBC URL configuration of Testcontainers with a custom Postgres image? I'd prefer to point it at a Dockerfile and have Testcontainers generate the image on the fly, but I could also accept a solution where I pre-build the database image and tell Testcontainers to pull it from Docker Hub.
For reference, my code is on Github at joeclark-phd/granite and the Dockerfile in question is in the "database" directory here. A sample test case is AgencyControllerIntegrationTest.java and you can see there's at least 15 lines of code that could be eliminated if I went to the JDBC URL approach.
Upvotes: 1
Views: 2389
Reputation: 96
Unfortunately, option 2 is still an open issue within testcontainers-java https://github.com/testcontainers/testcontainers-java/issues/4. Work is still being done to support custom images and custom registries with the special testcontainers jdbc urls. Until then you might need to find another approach.
Upvotes: 0
Reputation: 5076
There are different solutions to your question. I think a nice solution for you would be to set an application.properties
file like this:
spring.datasource.url = ${DB_HOST}:${DB_PORT}/"nameofDB"
spring.datasource.username = ${DB_USERNAME}
spring.datasource.password = ${DB_PASSWORD}
You should be able now to simply define the variables in your container. e.g.
docker run \
-it my_project_name \
-e DB_HOST=myGraniteDB \
-e DB_PORT=5432 \
-e DB_USERNAME=${TEST_DB_USERNAME} \
-e DB_USERNAME=${TEST_DB_PASSWORD} \
${granite_image_name}:${the_tag}
In alternative you could simply start your docker container like this:
docker run \
-it my_project_name \
${granite_image_name}:${the_tag} \
--spring.datasource.url=$test_db_url
Or even define a set of Externalized Configuration: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Upvotes: 0