Paulo's Blog

Testcontainers Initscript

June 22, 2020

This is the second part of a series of three posts about Testcontainers. In the first part the Testcontainers library was introduced. In this post we’ll explore a way to create test data for your tests using init scripts. We’re going expand upon the code introduced on the first part so you might want to do that, if you already know about Testcontainers you can accompany this post by cloning the repo here and checking out the simple-test tag.

The Problem

Let’s say that before your tests run you want to create some state before that. Perhaps you would like to have some tables populated so that you don’t have to create all that state on code. You can do that on the container setup by specifying a sql file like this:

    companion object {
        @Container
        val container = KPostgresContainer()
                .withInitScript("add_users.sql")
                .withExposedPorts(5432)
                .withDatabaseName("test")
                .withUsername("postgres")
                .withPassword("postgres")
    }

The withInitScript expects a file name and will search within your resources folder. We’re going to create the database using a sql script instead of relying on spring.jpa.hibernate.ddl-auto=create, so delete this line from application.properties. this is necessary for two reasons. First the create option drops existing data and creates it again. Second this creating is done only when Spring is started and withInitScript runs before that so if we tried only to add the data, there would be no table created.

Create the add_users.sql on the test/src/resources folder containing:

CREATE TABLE users(
    id INT,
    first_name VARCHAR,
    last_name VARCHAR
);

INSERT INTO users (id, first_name, last_name) VALUES (2, 'Addrianne', 'Lenker'), (3, 'Phoebe', 'Bridges');

The script is pretty straightforward, it just creates the database table and inserts two users on it. Now, let’s create a test to validate this new setup is working:

Add the following test to UserRepositoryTest.kt:

    @Test
    fun `test user are present`() {
        assertEquals("Addrianne", userRepository.findById(2).get().firstName)
        assertEquals("Phoebe", userRepository.findById(3).get().firstName)
    }

Run the test and it should pass, confirming that the script was run before the test starts. You can see the code for this post here. Just clone and checkout the tag initscript: git checkout initscript.

In the last post we’ll look at a more interesting pattern, to use a Docker image with data already prepopulated so that we don’t have to run init scripts every time our tests are started.


© 2021, blog.paulocosta.dev