Restore database state after integration test using Docker?
We are using PostgreSQL along with EAR deployed to JBoss. During the build process we have a development database dump that is used then in integration test: special artifact is deployed and tests communicate with the app using http client.
Currently, the database state changes during tests run, so we have no way but to put additional content for each test that modifies it, so no tests would depend each other. It takes really lots of time and patience as such test become even dependent on the order of records.
Is there a way to make a snapshot of DB so that to restore it after each test run with a reasonable amount of resources? Could Docker help? Or any other way around?
H2 is not the way, because we use some PostgreSQL-specific features. Tests may span multiple transactions, so I guess rollback would not help either.
3 Solutions collect form web for “Restore database state after integration test using Docker?”
One straightforward way with Docker is to have your database snapshot as a volume you reset and then mount into the beginning of your test run.
You can massage this data prior to your tests running (either have a tar of your entire starting database config or something else), then launch your PostgreSQL test database, with the test data mounted as a volume and your PostgreSQL pointing to this, for each test.
One option is to re-seed the data after each integration test is completed.
Spring offers such feature via SqlScriptsTestExecutionListener and @Sql annotation. I know you mentioned
JBoss, so if
Spring is not being used, I believe Arquillian might offer something similar.
In case re-seeding the DB becomes an expensive operation due to the amount of data used for integration testing, another option would be to use a
Docker image with the DB and seeded data already included. You would need to start the
DB with data container before each integration test is executed and stopped after it has completed, in other words, you would need to manage the container life-cycle for the duration of the integration tests. I blogged about how to accomplish this so a few months ago: Integration Testing using Spring Boot, Postgres and Docker, again, using
Spring Boot, but the ideas would be valid to use with another framework. It covers creating the
Docker images with imported data, generating the
JPA entities from existing schema, adding support for Integration Tests to start / stop container before and after each test is executed, and it could be easily extended to start more than one container per test or to execute them concurrently since the
Docker container is mapped to a host random port.
At this point it’s a compromise, starting each test from a know state (IMHO, the right approach) at the expense of either re-seed the data or start / stop containers for each individual test or run the tests in certain order and just re-seed the data before the test suite is execute.
You can do this by cloning the initial database and dropping the newly created test database after the test. When using the original database as a “TEMPLATE” this will probably only take milliseconds.
// Create "initial_database" before all tests are run and load fixtures etc.
// TEST SETUP BEFORE EACH TEST
CREATE DATABASE some_test_database_name TEMPLATE "initial_database";
// TEST TEARDOWN AFTER EACH TEST
DROP DATABASE some_test_database_name;