Skip to content

Instantly share code, notes, and snippets.

@asvanberg
Created September 7, 2024 21:44
Show Gist options
  • Save asvanberg/4d65be8f7d1f0abd558de4c8d2776bca to your computer and use it in GitHub Desktop.
Save asvanberg/4d65be8f7d1f0abd558de4c8d2776bca to your computer and use it in GitHub Desktop.
Solving the problem of emptying the database between each test when using Spring Boot and Testcontainers
/*
This showcases how to use a Testcontainers provided database to test a Spring
Boot application while isolating every test so that changes to the database
does not interfere with other tests.
It accomplishes this without any reliance on implementation details to empty
out specific tables or anything else. There is no global "rollback only"
transaction semantics. You can run assertions against the actual data in the
database if desired, including any schema changes.
It does all this by utilising mariadb-dump and taking a complete database dump
after Spring Boot has done its initialisation, and after each test it restores
the dump giving you back the clean initialised state.
*/
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.MariaDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@Testcontainers
class SomeTest {
@Container
@ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11");
@BeforeEach
void setUp() throws Exception {
String command = "mariadb-dump -u %s -p%s %s > /tmp/dump.sql".formatted(
mariaDBContainer.getUsername(),
mariaDBContainer.getPassword(),
mariaDBContainer.getDatabaseName()
);
var execResult = mariaDBContainer.execInContainer("sh", "-c", command);
if (execResult.getExitCode() != 0) {
throw new RuntimeException("Could not create a pre-test dump");
}
}
@AfterEach
void tearDown() throws Exception {
String command = "mariadb -u %s -p%s %s < /tmp/dump.sql".formatted(
mariaDBContainer.getUsername(),
mariaDBContainer.getPassword(),
mariaDBContainer.getDatabaseName()
);
var execResult = mariaDBContainer.execInContainer("sh", "-c", command);
if (execResult.getExitCode() != 0) {
throw new RuntimeException("Could not restore pre-test dump");
}
}
@Test
void some_test() throws Exception {
// each test has its own fresh copy of the database
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment