blog podcast

Testcontainers

It all seemed so simple, you add testcontainers to your java project, it instantiates your docker containers and everything works. And in a way it is also quite simple. The library does start your docker containers, it even has annotations that helps it listen to junit5 life cycle events and behave accordingly. But as I found out today, simple is not always simple.

It’s this constant feeling I get where I feel that Java is like a very beautiful puzzle, where the pieces almost, but not quite, fit together. The thing is, it does start up your test container, but at a random port. Now this might be an issue if you want to connect to it. To mitigate this there are two possible techniques:

One which I found quite elegant (although not fully transparent). One could use a driver class for testcontainer in ones datasource. This way the driver could take care of both starting the container, and making sure that your DB library is using the correct port when trying to connect to the DB. Unfortunately this didn’t reach the whole way for me. In the end it seemed that the testdriver decided on creating one container for my flyway migrations, and another one for my normal connection. Now, this meant that the DB that the normal connection didn’t have any flyway applied, and was hence not even a DB..

Then the other way. One create a configuration, and then makes sure that after starting the container manually; bye bye smart listening to junit5 life cycle events :’(. That works, but now one has kind of hijacked all of that smart life cycle and configuration stuff that the testcontainer project can do.

In the end it was a very frustrating endeavor which luckily for me ended up with working tests in the end. And for what it’s worth, I believe that when there’s no frustration there’s no learning.

Code of the Day

The example is taken from testcontainers web page. Easy as pie…

@Testcontainers
public class RedisBackedCacheIntTest {

    private RedisBackedCache underTest;

    // container {
    @Container
    public GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine"))
                                            .withExposedPorts(6379);