Custom docker image with test data: How to use as a template
jomatt opened this issue · comments
This library seems to be exactly what I was looking for. I have a Spring Boot project with Flyway. In order to speed up integration tests, I want to make use of the templating feature that is mentioned in the README:
Note that the Docker provider is especially useful if you need to use some database extensions, or if you want to prepare a custom docker image containing some test data. In such cases, you can use any docker image compatible with the official docker images of the supported databases.
So I built a custom docker image including test data inside the postgres
database. I also created a PostgreSQLContainerCustomizer
bean to explicitly set the database name, assuming that the library would pick up this database name and use this DB as the template.
@Configuration
public class TestConfiguration {
@Bean
public PostgreSQLContainerCustomizer postgresContainerCustomizer() {
return container -> container
.withDatabaseName("postgres")
.waitingFor(Wait.forLogMessage(".*database system is ready to accept connections.*", 1));
}
}
However, I found out that the library always creates a clean database inside my custom docker image when I start my integration tests. This clean DB is then picked up by Flyway to run the migrations (instead of using the already populated and migrated postgres
DB inside the custom docker image):
This is my Dockerfile
that I use to build the custom image:
FROM timescale/timescaledb
RUN mkdir -p /var/lib/postgresql-static/data
ENV PGDATA /var/lib/postgresql-static/data
ENV DATA_DUMP /tmp/data_dump.sql
COPY data_dump.sql $DATA_DUMP
COPY init_db.sh /docker-entrypoint-initdb.d
and the init_db.sh
file:
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
EOSQL
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$DATA_DUMP"
Am I missing something? Any help would be greatly appreciated.
@tomix26 thx for the swift answer - it works like a charm.
Another question: is there a way to programatically reset the DB without using the refresh
property on the @AutoConfigureEmbeddedDatabase
annotation? We have some tests that need to reset the state of the DB and others that don't. So it would be helpful to define for each test separately if the DB should be reset or not - instead of depending on a fixed refresh mode like AFTER_CLASS
or AFTER_EACH_TEST_METHOD
If you are using Flyway, you can use the @FlywayTest
annotation instead. It's possible to place the annotation even on a method level and the effect is the same as in case of the @AutoConfigureEmbeddedDatabase(refresh = ...)
annotation, check out an example here.
Nevertheless, if you really want to control the reset programmatically, you can inject an embedded data source into your test class and use a lower-level API of the library to get a corresponding database context and reset it manually. See the snippet below.
@RunWith(SpringRunner.class)
@AutoConfigureEmbeddedDatabase
public class DatabaseContextIntegrationTest {
@Autowired
private DataSource dataSource;
@Test
public void testMethod1() {
// Potentially dirty database from previous tests
}
@Test
public void testMethod2() {
DatabaseContext databaseContext = AopProxyUtils.getDatabaseContext(dataSource);
databaseContext.reset();
// Fresh database ensured by manual reset
}
@Test
public void testMethod3() {
// Dirty database that contains data from the previous test
}
}
Note that the order in which each test method is called can be non-deterministic, so the comments are just for illustrative purposes.
Ok, I guess it solved the problem. So, I'm closing the issue. Feel free to reopen it if you have more questions.