Testcontainers module for creating throwaway MySQL database containers for integration testing
npx @tessl/cli install tessl/maven-org-testcontainers--mysql@1.21.1The Testcontainers MySQL module provides a way to create lightweight, throwaway MySQL database instances within Docker containers for integration testing. It enables developers to write tests against real MySQL databases without requiring manual database setup or external infrastructure, ensuring tests are repeatable, isolated, and can run anywhere Docker is available.
Core Package:
org.testcontainers:mysql:1.21.4 (this package)org.testcontainers:testcontainers (core package, provided transitively)JDBC Driver (Required Separately):
com.mysql:mysql-connector-j:8.x (recommended for MySQL 8.0+)mysql:mysql-connector-java:5.x (for older applications)R2DBC Support (Optional):
org.testcontainers:r2dbc:1.21.4 (for reactive database access)io.asyncer:r2dbc-mysql:1.0.0 (R2DBC MySQL driver)System Requirements:
Full Class Name: org.testcontainers.containers.MySQLContainer<SELF extends MySQLContainer<SELF>>
Inheritance: Extends JdbcDatabaseContainer<SELF> which extends GenericContainer<SELF>
Type Parameter: SELF is the self-referential type for fluent method chaining
Key Methods (Quick Reference):
MySQLContainer(String|DockerImageName)withDatabaseName(String), withUsername(String), withPassword(String), withConfigurationOverride(String)start(): void, stop(): void, isRunning(): booleangetJdbcUrl(): String, createConnection(String): Connection, getDriverClassName(): StringwithInitScript(String), withInitScripts(String...|Iterable<String>)withStartupTimeoutSeconds(int), withConnectTimeoutSeconds(int)withUrlParam(String, String)withReuse(boolean)Database:
"test""test""test"3306 (mapped to random available host port)Container:
"mysql:8.0", "mysql:5.7.34")120 seconds120 secondsfalse (disabled by default)JDBC URL:
useSSL=false, allowPublicKeyRetrieval=truejdbc:mysql://host:port/database?useSSL=false&allowPublicKeyRetrieval=true[&urlParams]"localhost" but may differ in complex networking setupsgetMappedPort(3306) to retrieve)Driver Detection:
com.mysql.cj.jdbc.Driver (8.x) or com.mysql.jdbc.Driver (5.x)NoDriverFoundException if neither driver is foundContainer Instance:
start() method blocks until container is ready (throws ContainerLaunchException or IllegalStateException on failure)stop() method blocks until container is stoppedstart()JDBC Connections:
R2DBC:
Required Sequence:
new MySQLContainer<>(DockerImageName.parse("mysql:8.0")).withDatabaseName("testdb").withUsername("user")...container.start() (blocks until ready)container.getJdbcUrl(), container.createConnection(""), etc.container.stop() or use try-with-resourcesAutoCloseable Support:
MySQLContainer implements AutoCloseabletry (MySQLContainer<?> mysql = ...) { ... }Startup Process:
"SELECT 1")withInitScript())Shutdown Process:
ContainerLaunchException:
IllegalStateException:
NoDriverFoundException:
getJdbcDriverInstance() or createConnection() if MySQL JDBC driver is not found on classpathcom.mysql:mysql-connector-j or mysql:mysql-connector-java)SQLException:
createConnection() if connection cannot be established within configured timeout periodBasic Usage Pattern:
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb")) {
mysql.start();
// Use container
String jdbcUrl = mysql.getJdbcUrl();
}JUnit 5 Integration:
@Testcontainers
public class MySQLTest {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
// Container automatically started/stopped by framework
}Spring Boot Integration:
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}Container Reuse (Development Only):
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withReuse(true); // Requires testcontainers.reuse.enable=true in ~/.testcontainers.propertiesConfiguration Immutability:
start() is calledstart()Password Constraints:
"root" with MYSQL_ROOT_HOST environment variable set to "%"ContainerLaunchException"test" if not specifiedInitialization Scripts:
src/test/resources/)Port Mapping:
getMappedPort(3306) to retrieve the mapped host portgetMappedPort() or getJdbcUrl()Container Reuse:
testcontainers.reuse.enable=true in ~/.testcontainers.propertiestestImplementation "org.testcontainers:mysql:1.21.4"<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.21.4</version>
<scope>test</scope>
</dependency>Important: This module does not automatically include a MySQL JDBC driver. You must add a MySQL JDBC driver dependency to your project (e.g., com.mysql:mysql-connector-j or mysql:mysql-connector-java).
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;For R2DBC (reactive) support:
import org.testcontainers.containers.MySQLR2DBCDatabaseContainer;
import org.testcontainers.containers.MySQLR2DBCDatabaseContainerProvider;
import io.r2dbc.spi.ConnectionFactoryOptions;import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
// Create and start a MySQL container
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))) {
mysql.start();
// Get connection details
String jdbcUrl = mysql.getJdbcUrl();
String username = mysql.getUsername();
String password = mysql.getPassword();
// Create a JDBC connection and run queries
try (Connection conn = mysql.createConnection("")) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
rs.next();
int result = rs.getInt(1);
// result == 1
}
}The MySQL module is built on the Testcontainers framework and provides the following key components:
JdbcDatabaseContainer, providing MySQL-specific configuration and lifecycle managementMySQLR2DBCDatabaseContainer adapterThe container automatically:
useSSL=false, allowPublicKeyRetrieval=true)Create and configure MySQL containers with custom settings including Docker image version, database name, credentials, and server configuration.
class MySQLContainer<SELF extends MySQLContainer<SELF>> extends JdbcDatabaseContainer<SELF> {
// Constructors
MySQLContainer(String dockerImageName);
MySQLContainer(DockerImageName dockerImageName);
// Configuration methods (fluent interface, return SELF)
SELF withDatabaseName(String databaseName);
SELF withUsername(String username);
SELF withPassword(String password);
SELF withConfigurationOverride(String configPath);
// Getters
String getDatabaseName(); // default: "test"
String getUsername(); // default: "test"
String getPassword(); // default: "test"
}Obtain JDBC connection details and create database connections for executing SQL queries in tests.
class MySQLContainer<SELF extends MySQLContainer<SELF>> {
// Connection information
String getJdbcUrl(); // Returns: jdbc:mysql://host:port/database?useSSL=false&allowPublicKeyRetrieval=true[&urlParams]
String getDriverClassName(); // Returns: "com.mysql.cj.jdbc.Driver" (8.x) or "com.mysql.jdbc.Driver" (5.x)
String getDatabaseName();
String getUsername();
String getPassword();
String getTestQueryString(); // Returns: "SELECT 1"
// Connection creation (inherited from JdbcDatabaseContainer)
Connection createConnection(String queryString) throws SQLException;
Driver getJdbcDriverInstance() throws NoDriverFoundException;
}Execute SQL scripts to set up database schema and test data when the container starts.
class MySQLContainer<SELF extends MySQLContainer<SELF>> {
// Inherited from JdbcDatabaseContainer
SELF withInitScript(String initScriptPath);
SELF withInitScripts(String... initScriptPaths);
SELF withInitScripts(Iterable<String> initScriptPaths);
}Control container startup, shutdown, and monitor container state.
class MySQLContainer<SELF extends MySQLContainer<SELF>> {
// Inherited from GenericContainer
void start(); // Blocks until container is ready, throws ContainerLaunchException or IllegalStateException
void stop(); // Stops and removes container
boolean isRunning(); // Returns current running state
// Configuration
SELF withReuse(boolean reuse); // Enable container reuse (requires testcontainers.reuse.enable=true)
}Customize JDBC URL parameters and configure startup/connection timeouts.
class MySQLContainer<SELF extends MySQLContainer<SELF>> {
// Inherited from JdbcDatabaseContainer
SELF withUrlParam(String paramName, String paramValue);
SELF withStartupTimeoutSeconds(int startupTimeoutSeconds); // default: 120
SELF withConnectTimeoutSeconds(int connectTimeoutSeconds); // default: 120
}Use MySQL containers with R2DBC for reactive, non-blocking database access.
class MySQLR2DBCDatabaseContainer implements R2DBCDatabaseContainer {
MySQLR2DBCDatabaseContainer(MySQLContainer<?> container);
static ConnectionFactoryOptions getOptions(MySQLContainer<?> container);
ConnectionFactoryOptions configure(ConnectionFactoryOptions options);
// Lifecycle methods (delegated to wrapped MySQLContainer)
void start();
void stop();
}
class MySQLR2DBCDatabaseContainerProvider implements R2DBCDatabaseContainerProvider {
static final String DRIVER = "mysql";
boolean supports(ConnectionFactoryOptions options);
R2DBCDatabaseContainer createContainer(ConnectionFactoryOptions options);
ConnectionFactoryMetadata getMetadata(ConnectionFactoryOptions options);
}Advanced container customization including environment variables, command overrides, port mapping, and logging.
class MySQLContainer<SELF extends MySQLContainer<SELF>> {
// Inherited from GenericContainer
SELF withEnv(String key, String value);
SELF withEnv(Map<String, String> env);
SELF withCommand(String... commandParts);
SELF withExposedPorts(Integer... ports);
SELF withLogConsumer(Consumer<OutputFrame> consumer);
// Information methods
String getHost(); // Returns: "localhost" typically
Integer getMappedPort(int originalPort); // Returns mapped host port for container port
List<Integer> getExposedPorts();
Set<Integer> getLivenessCheckPortNumbers();
}class MySQLContainer<SELF extends MySQLContainer<SELF>> {
static final String NAME = "mysql";
static final Integer MYSQL_PORT = 3306;
}The module throws the following exceptions:
getJdbcDriverInstance() or createConnection())createConnection() if the connection cannot be established within the configured timeout periodFor advanced use cases, the module provides a factory class for creating MySQL containers. This is primarily used internally by Testcontainers for JDBC URL-based container instantiation.
class MySQLContainerProvider extends JdbcDatabaseContainerProvider {
boolean supports(String databaseType); // Returns true for "mysql"
JdbcDatabaseContainer newInstance();
JdbcDatabaseContainer newInstance(String tag);
JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl);
}Note: Most users should use MySQLContainer directly rather than MySQLContainerProvider. The provider is used internally by the Testcontainers JDBC support for connection strings like jdbc:tc:mysql:8.0:///testdb.
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
@Testcontainers
public class MySQLJUnit5Test {
@Container
private static MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb");
@Test
public void testDatabase() {
// Container is automatically started before tests and stopped after
String jdbcUrl = mysql.getJdbcUrl();
// Run test...
}
}import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
@SpringBootTest
@Testcontainers
public class SpringBootMySQLTest {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("springtest");
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
// Spring Boot tests...
}public abstract class AbstractMySQLTest {
protected static final MySQLContainer<?> MYSQL_CONTAINER;
static {
MYSQL_CONTAINER = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb")
.withReuse(true);
MYSQL_CONTAINER.start();
}
protected String getJdbcUrl() {
return MYSQL_CONTAINER.getJdbcUrl();
}
}