workerjoe
workerjoe

Reputation: 2663

Can I use Testcontainers in JDBC URL mode with a custom Dockerfile?

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:

  1. 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.

  2. 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

Answers (2)

Aidan Do
Aidan Do

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

Stefano
Stefano

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

Related Questions