This document covers executing SQL initialization scripts to set up database schema and test data when the MySQL container starts.
Initialization Methods (Fluent Interface, Return SELF):
withInitScript(String initScriptPath) - Execute single SQL script from classpathwithInitScripts(String... initScriptPaths) - Execute multiple scripts (varargs)withInitScripts(Iterable<String> initScriptPaths) - Execute multiple scripts (iterable)Execution Details:
src/test/resources/)ContainerLaunchException or IllegalStateExceptionConstraints:
start()Execute a single SQL script from the classpath when the container starts.
/**
* Sets a single SQL script to be executed when the container starts.
* The script is loaded from the classpath and executed against the database
* before the container is considered ready.
*
* If this method is called multiple times, only the last script is used.
* To execute multiple scripts, use withInitScripts() instead.
*
* @param initScriptPath path to the SQL script file on the classpath (e.g., "schema.sql" or "db/schema.sql")
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if initScriptPath is null or empty
* @throws ContainerLaunchException if script file is not found on classpath or contains invalid SQL
*/
SELF withInitScript(String initScriptPath);Usage Example:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
// Assumes schema.sql is in src/test/resources/
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScript("schema.sql");
mysql.start();
// Container is ready and schema.sql has been executedExample schema.sql:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
total DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com');Execute multiple SQL scripts in a specified order using varargs.
/**
* Sets multiple SQL scripts to be executed in order when the container starts.
* Scripts are loaded from the classpath and executed sequentially.
* Each script must complete successfully before the next one begins.
*
* @param initScriptPaths paths to SQL script files on the classpath (in execution order)
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if initScriptPaths is null or contains null/empty elements
* @throws ContainerLaunchException if any script file is not found on classpath or contains invalid SQL
*/
SELF withInitScripts(String... initScriptPaths);Usage Example:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScripts(
"schema.sql", // Create tables
"seed-data.sql", // Insert test data
"stored-procedures.sql" // Create stored procedures
);
mysql.start();
// All three scripts have been executed in orderExecute multiple SQL scripts from an iterable collection.
/**
* Sets multiple SQL scripts to be executed in order when the container starts.
* Scripts are loaded from the classpath and executed in iteration order.
* Each script must complete successfully before the next one begins.
*
* @param initScriptPaths iterable collection of paths to SQL script files on the classpath
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if initScriptPaths is null or contains null/empty elements
* @throws ContainerLaunchException if any script file is not found on classpath or contains invalid SQL
*/
SELF withInitScripts(Iterable<String> initScriptPaths);Usage Example:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.util.Arrays;
import java.util.List;
List<String> scripts = Arrays.asList(
"01-schema.sql",
"02-seed-users.sql",
"03-seed-products.sql"
);
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScripts(scripts);
mysql.start();import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class InitializationTest {
public void testWithInitializedDatabase() throws Exception {
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("app_test")
.withInitScripts(
"db/schema.sql",
"db/test-data.sql"
)) {
mysql.start();
// Database is ready with schema and test data
try (Connection conn = mysql.createConnection("")) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM users");
rs.next();
int userCount = rs.getInt(1);
// userCount reflects data from test-data.sql
System.out.println("Users in database: " + userCount);
}
}
}
}Execution Order:
Script Location:
src/test/resources/)Script Content:
-- or /* */)Error Handling:
ContainerLaunchException or IllegalStateExceptionPerformance Considerations:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.util.ArrayList;
import java.util.List;
boolean includeTestData = true;
List<String> scripts = new ArrayList<>();
scripts.add("schema.sql"); // Always include schema
if (includeTestData) {
scripts.add("test-data.sql"); // Conditionally include test data
}
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScripts(scripts);import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
String environment = System.getProperty("test.env", "default");
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScripts(
"schema.sql",
"data-" + environment + ".sql" // e.g., data-default.sql or data-integration.sql
);For large datasets, consider:
Example:
// Instead of large init script, generate data after startup
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScript("schema.sql"); // Only schema
mysql.start();
// Generate test data programmatically
try (Connection conn = mysql.createConnection("")) {
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO users (username, email) VALUES (?, ?)");
for (int i = 0; i < 10000; i++) {
stmt.setString(1, "user" + i);
stmt.setString(2, "user" + i + "@example.com");
stmt.addBatch();
if (i % 1000 == 0) {
stmt.executeBatch();
}
}
stmt.executeBatch();
}Initialization scripts work alongside configuration overrides:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("myapp")
.withConfigurationOverride("mysql-config") // Custom my.cnf settings
.withInitScripts(
"schema.sql",
"seed-data.sql"
);
mysql.start();
// Container has custom MySQL configuration AND initialized databaseIF NOT EXISTS clauses where possible to make scripts rerunnable01-schema.sql, 02-data.sql)-- schema-idempotent.sql
-- Create database if it doesn't exist
CREATE DATABASE IF NOT EXISTS myapp;
USE myapp;
-- Create tables if they don't exist
CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS sessions (
id VARCHAR(36) PRIMARY KEY,
user_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Insert test data only if it doesn't exist
INSERT INTO users (username, email)
SELECT 'testuser', 'test@example.com'
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'testuser');-- transactional-init.sql
START TRANSACTION;
CREATE TABLE accounts (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
balance DECIMAL(10, 2) NOT NULL DEFAULT 0
);
INSERT INTO accounts (name, balance) VALUES
('Alice', 1000.00),
('Bob', 500.00);
COMMIT;import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.containers.ContainerLaunchException;
try {
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withInitScript("invalid-script.sql");
mysql.start();
} catch (ContainerLaunchException e) {
// Script execution failed
System.err.println("Init script failed: " + e.getMessage());
// Check script syntax and content
}Script Not Found:
src/test/resources/ directoryScript Execution Fails:
Performance Issues:
Timeout Issues:
withStartupTimeoutSeconds(300)