Skip to content

ydespreaux/testcontainers

Repository files navigation

Integration tests with testcontainers

This library defines docker containers for integration tests. Its implementation is based on the testcontainers.org library.

Container types:

  • MySQL
    • Initializing database with sql scripts
  • Cassandra
    • Initializing database with cql scripts
  • Elasticsearch
  • Kafka
    • Schema registry for AVRO message
    • Kafka-Connect Container

Versions

spring-testcontainers testcontainers JUnit version compatibility
1.2.2 1.11.1 Junit 4, Junit 5
1.2.1 1.10.6 Junit 4, Junit 5
1.2.0 1.10.6 Junit 4
1.1.0 1.10.6 Junit 4
1.0.0 1.8.3 Junit 4

Prerequisites

Using this library requires a Docker configuration beforehand so that the docker containers can be running:

  • Docker version should be at least 1.6.0
  • Docker environment should have more than 2GB free disk space
  • File should be mountable
  • Expose daemon on tcp://localhost:2375 without TLS

MySQL

Add the Maven dependency

<dependency>
    <groupId>com.github.ydespreaux.testcontainers</groupId>
    <artifactId>testcontainers-mysql</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

Using Junit 5 (version 1.2.1)

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.11.1</version>
    <scope>test</scope>
</dependency>

Quick Start

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer();
}

By default the MySQL image used is 'mysql: 5.7.22'. The URL of the image and the version are configurable. Below is an example to use version 5.7.21 of the image.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer("5.7.21");
}

When the docker container has started, the following properties are initialized in the spring boot context:

spring boot property Default value Note
spring.datasource.url jdbc:mysql://localhost:/db_test?useSSL=false The port is generated randomly
spring.datasource.driver-class-name com.mysql.jdbc.Driver
spring.datasource.username db_user_test
spring.datasource.password *********** The user's password is automatically generated by default
spring.datasource.platform mysql

The withRegisterSpringbootProperties (boolean) method is used to initialize or not the spring boot context of the properties above. The following example does not update the spring boot properties:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer("5.7.21")
        .withRegisterSpringbootProperties(false);
}

The name of the spring boot properties can be changed using the following methods:

Method Description Default value
withDriverClassSystemProperty Modify the property corresponding to the MySQL driver spring.datasource.driver-class-name
withUrlSystemProperty Modify the property corresponding to the URL spring.datasource.url
withUsernameSystemProperty Modify the property corresponding to the name of the MySQL user spring.datasource.username
withPasswordSystemProperty Modify the property corresponding to the password of the MySQL user spring.datasource.password
withPlatformSystemProperty Modify the property corresponding to the platform spring.datasource.platform

Setting up the MySQL database:

Method Description Default value
withDatabaseName Modify the name of the database db_test
withUsername Modify the name of the MySQL user db_user_test
withPassword Modify the password of the MySQL user Automatically generated
withRootPassword Change the ROOT password Automatically generated
withConfigurationOverride Modify the MySQL configuration file

Initialization of the schema of the database:

Running a sql script:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer("5.7.21")
        .withMySqlInit("mysql-init/mysql-init.sql");
}

The mysql-init.sql file (found in the mysql-init directory) will be executed after the container starts.

Running a set of sql scripts:

Example to run 2 sql scripts:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer("5.7.21")
        .withMySqlInit("mysql-init/mysql-init-1.sql")
        .withMySqlInit("mysql-init/mysql-init-2.sql");
}

Example to run all the sql scripts contained in the 'mysql-init' directory:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final MySQLContainer mySqlContainer = new MySQLContainer("5.7.21")
        .withMySqlInitDirectory("mysql-init");
}

Sample with Junit 5 (version 1.2.1)

@Testcontainers
public class ITMySQLTest {

    @Container
    public static final MySQLContainer mySqlContainer = new MySQLContainer();
}

Cassandra

Add the Maven dependency

<dependency>
    <groupId>com.github.ydespreaux.testcontainers</groupId>
    <artifactId>testcontainers-cassandra</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

Using Junit 5 (version 1.2.1)

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.11.1</version>
    <scope>test</scope>
</dependency>

Quick Start

@RunWith(SpringJUnit4ClassRunner.class)
public class ITCassandraTest {

    @ClassRule
    public static final CassandraContainer mySqlContainer = new CassandraContainer();
}

By default the image cassandra used is 'cassandra: 3.11'. The URL of the image and the version is configurable. Below is an example to use version 3 of the image.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITCassandraTest {

    @ClassRule
    public static final CassandraContainer mySqlContainer = new CassandraContainer("3");
}

When the docker container has started, the following properties are initialized in the spring boot context:

Spring boot property Default value Notes
spring.data.cassandra.contact-points localhost The host is the docker hostname
spring.data.cassandra.port 33001 The port is generated randomly

The withRegisterSpringbootProperties (boolean) method is used to initialize or not the spring boot context of the properties above.

The name of the spring boot properties can be changed using the following methods:

Method Description Default value
withContactPointsSystemProperty Changes the ownership of cassandra cluster uris Docker hostname
withCassandraPortSystemProperty Modify the property corresponding to the port cassandra The port is generated randomly

Initialization of the schema of the database:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITMySQLTest {

    @ClassRule
    public static final CassandraContainer cassandraContainer = new CassandraContainer()
        .withCqlScriptDirectory("db-schema");

}

The withCqlScriptDirectory (...) method takes a parameter from the directory path. The set of scripts cql will be executed after the start of the container.

Sample with Junit 5 (version 1.2.1)

@Testcontainers
public class ITCassandraTest {

    @Container
    public static final CassandraContainer mySqlContainer = new CassandraContainer();
}

Elasticsearch

Add the Maven dependency

<dependency>
    <groupId>com.github.ydespreaux.testcontainers</groupId>
    <artifactId>testcontainers-elasticsearch</artifactId>
    <version>1.1.0</version>
    <scope>test</scope>
</dependency>

Using Junit 5 (version 1.2.1)

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.11.1</version>
    <scope>test</scope>
</dependency>

Quick Start

@RunWith(SpringJUnit4ClassRunner.class)
public class ITElasticsearchTest {

    @ClassRule
    public static final ElasticsearchContainer elasticContainer = new ElasticsearchContainer();
}

By default, the elasticsearch image used is 'elasticsearch / elasticsearch: 5.6.8'. The URL of the image and the version is configurable. Below is an example to use version 6.4.2 of the image.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITElasticsearchTest {

    @ClassRule
    public static final ElasticsearchContainer elasticContainer = new ElasticsearchContainer(Versions.ELASTICSEARCH_VERSION);
}

Note that security is disabled.

When the docker container has started, the following properties are initialized in the spring boot context:

Spring boot property Default value Notes
spring.elasticsearch.jest.uris http://localhost:33001 The port is generated randomly
spring.elasticsearch.rest.uris http://localhost:33001 The port is generated randomly

The withRegisterSpringbootProperties (boolean) method is used to initialize or not the spring boot context of the properties above.

The name of the spring boot properties can be changed using the following methods:

Méthode Description
withJestUrisSystemProperty Modifies the property corresponding to uris of elasticsearch for jest
withRestUrisSystemProperty Modifies the property corresponding to the uris of elasticsearch for the Rest elasticsearch API

Initialization script (since 1.1.0)

An initialization script file can be provided using the fileInitScript parameter, in which case it will be executed against the local Elasticsearch cluster. The file extension defines the file format: json for JSON format, anything else for custom format.

JSON format

The provided JSON file should contain a list of requests to be sent, one by one, to the Elasticsearch cluster. Each request definition has three properties:

  • the name (in uppercase) of the request method to be used for the current request (one of PUT, POST, DELETE)
  • the path part of the URL (should not start with slash)
  • the payload

The payload should not be defined for DELETE requests. Some Elasticsearch requests do not require a payload (eg. POST index/_refresh), in which case define the payload as {}

Example:

To send a POST request to http://localhost:9200/test_index/test_type/_mapping, followed by a DELETE request to http://localhost:9200/test_index/test_type/1:

[
    {
        "method": "POST",
        "path": "test_index/test_type/_mapping",
        "payload": {
            "test_type": {
                "properties": {
                    "name": {
                        "type": "keyword"
                    },
                    "lastModified": {
                        "type": "date"
                    }
                }
            }
        }
    },
    {
        "method": "DELETE",
        "path": "test_index/test_type/1"
    }
]

Custom format

Each line defines a request to be sent to the Elasticsearch cluster, and it has three parts separated by colon ':'

  • the name (in uppercase) of the request method to be used for the current request (one of PUT, POST, DELETE)
  • the path part of the URL (should not start with slash)
  • the JSON to send to Elasticsearch as payload (it should be empty for DELETE requests)

Note: Empty lines are ignored, as well as lines starting with the '#' sign.

Examples :

To send a POST request to http://localhost:9200/test_index/test_type/_mapping:

POST:test_index/test_type/_mapping:{ "test_type" : { "properties" : { "name" : { "type" : "keyword" }, "lastModified" : { "type" : "date" } } } }

To send a DELETE request to http://localhost:9200/test_index/test_type/1 without content; note the colon at the end, for there is no JSON data in case of a DELETE.

DELETE:test_index/test_type/1:

Sample with Junit 5 (version 1.2.1)

@Testcontainers
public class ITElasticsearchTest {

    @Container
    public static final ElasticsearchContainer elasticContainer = new ElasticsearchContainer();
}

Kafka

Add the Maven dependency

<dependency>
    <groupId>com.github.ydespreaux.testcontainers</groupId>
    <artifactId>testcontainers-kafka</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

Using Junit 5 (version 1.2.1)

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.11.1</version>
    <scope>test</scope>
</dependency>

Container Kafka

Quick Start

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaContainer kafkaContainer = new ConfluentKafkaContainer();
}

By default the Kafka image used is 'confluentinc / cp-kafka: 3.3.1'.

The version is configurable. Below is an example to use version 4.0.0 of the image.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer("4.0.0");
}

Activate schema registry.

By default, the registry schema is not active. Below is an example to activate the registry schema.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer().withSchemaRegistry(true);
}

Configuration

When the docker container has started, the following properties are initialized in the spring boot context:

Spring boot property Default value Notes
spring.kafka.bootstrap-servers localhost:33001 The broker's port is generated randomly
spring.kafka.properties.schema.registry.url http://localhost:33002 The registry schema port is generated randomly. This property is initialized only if the registry schema is enabled.

The withRegisterSpringbootProperties (boolean) method is used to initialize or not the spring boot context of the properties above.

The name of the spring boot properties can be changed using the following methods:

Method Description Default value
withBrokerServersSystemProperty Modifies the property corresponding to the uris of the brokers spring.kafka.bootstrap-servers
withSchemaRegistrySystemProperty Modifies the property corresponding to the url of schema registry spring.kafka.properties.schema.registry.url

Access to urls

Method Description Default value
getBootstrapServers() Return the kafka brokers url localhost:33001
getZookeeperServer() Returns the url of the zookeeper server localhost:33001
getZookeeperConnect() Returns the local url of the zookeeper server zookeeper:33001

Topics configuration

Added the withTopic method to create a topic with the name of the topic, the number of partitions and the type of topic compacted or not.

Method Description
withTopic(topic, partitions, compact) Creating a topic when the container is initialized
withTopic(TopicConfiguration) Creating a topic when the container is initialized

Example:

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer()
        .withTopic("topic1-non-compact", 3, false)
        .withTopic("topic2-compact", 3, true);
}

Sécurité SSL (version 1.2.0).

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    public static final Certificates kafkaServerCertificates = new Certificates("secrets/kafka.server.keystore.jks", "0123456789", "secrets/kafka.truststore.jks", "0123456789");
    public static final Certificates kafkaClientCertificates = new Certificates("secrets/kafka.client.keystore.jks", "0123456789", "secrets/kafka.truststore.jks", "0123456789");

    @ClassRule
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer()
        .withKafkaServerCertificates(kafkaServerCertificates)
        .withKafkaClientCertificates(kafkaClientCertificates)
        .withTopic("TOPIC_1", 1, true)
        .withAcls(new AclsOperation[]{AclsOperation.READ, AclsOperation.WRITE}, "TOPIC_1", "my-group");
}    

When the docker container has started, the properties corresponding to the SSL configuration are initialized in the context of spring boot:

Spring boot property Description
spring.kafka.security.protocol Security protocol : SSL
spring.kafka.ssl.key-password Keystore password (client)
spring.kafka.ssl.key-store-location Keystore location (client)
spring.kafka.ssl.key-store-password Keystore password
spring.kafka.ssl.trust-store-location Truststore location
spring.kafka.ssl.trust-store-password Truststore password
spring.kafka.properties.ssl.endpoint.identification.algorithm Identification algorithm set to empty ("")

If the client certificate is not initialized when the container is launched, the spring boot properties related to the SSL configuration will not be initialized.

The name of the spring boot properties can be changed using the following methods:

Methode Default value
withSecurityProtocolSystemProperty spring.kafka.security.protocol
withKeyPasswordSystemProperty spring.kafka.ssl.key-password
withKeystoreLocationSystemProperty spring.kafka.ssl.key-store-location
withKeystorePasswordSystemProperty spring.kafka.ssl.key-store-password
withTruststoreLocationSystemProperty spring.kafka.ssl.trust-store-location
withTruststorePasswordSystemProperty spring.kafka.ssl.trust-store-password
withIdentificationAlgorithmSystemProperty spring.kafka.properties.ssl.endpoint.identification.algorithm

Sample with Junit 5 (version 1.2.1)

@Testcontainers
public class ITKafkaTest {

    @Container
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer("4.0.0");
}

Container Kafka Connect

Quick Start

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaConnectContainer kafkaContainer = new ConfluentKafkaConnectContainer();
}

By default the Kafka connect image used is 'confluentinc / cp-kafka-connect: 4.1.0'. Compatibility of Kafka messages is fixed with version 0.11.0 by default.

The version is configurable. Below is an example to use version 4.0.0 of the image.

@RunWith(SpringJUnit4ClassRunner.class)
public class ITKafkaTest {

    @ClassRule
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer("4.0.0");
}

Configuration

When the docker container has started, the following properties are initialized in the spring boot context:

Spring boot property Default value Notes
spring.kafka.bootstrap-servers localhost: The broker's port is generated randomly
spring.kafka.properties.schema.registry.url http://localhost: The registry schema port is generated randomly. This property is initialized only if the registry schema is enabled.
spring.kafka-connect.rest-app http://localhost: The port of the Rest application is generated randomly.

The withRegisterSpringbootProperties (boolean) method is used to initialize or not the spring boot context of the properties above.

The name of the spring boot properties can be changed using the following methods:

Method Description Default value
withBrokerServersSystemProperty Modifies the property corresponding to the uris of the brokers spring.kafka.bootstrap-servers
withSchemaRegistrySystemProperty Modifies the property corresponding to the url of schema registry spring.kafka.properties.schema.registry.url
withRestAppSystemProperty Modifies the property corresponding to the url of the REST application spring.kafka-connect.rest-app

Initialization method of the worker:

Method Description Default value
withKeyConverter Defines the type of "Converter" of the message keys org.apache.kafka.connect.json.JsonConverter
withValueConverter Defines the type of "Converter" message values org.apache.kafka.connect.json.JsonConverter
withPlugins Add plugins No plugin

In the case of an Avro converter, the registry schema is automatically configured if it has been activated.

Herder initialization method in standalone mode:

Method Description Default value
withOffsetStorageFilename Name of the offsets storage file connect-offsets-file.txt

Herder initialization method in distributed mode:

Method Description Default value
withGroupId Name of the group kafka-connect-group
withConfigStorageTopic Name of the configuration topic connect-config
withOffsetStorageTopic Name of the offsets topic connect-offsets
withOffsetStoragePartition Number of offsets topic partitions 3
withStatusStorageTopic Name of the status topic connect-status
withStatusStoragePartition Number of partitions of the status topic 3

Access to urls

Method Description Default value
getBootstrapServers() Return the kafka brokers url localhost:
getZookeeperServer() Returns the url of the zookeeper server localhost:
getZookeeperConnect() Returns the local url of the zookeeper server zookeeper:
getRestAppServers() Returns the url of the REST application http://localhost:

Sample with Junit 5 (version 1.2.1)

@Testcontainers
public class ITKafkaTest {

    @Container
    public static final ConfluentKafkaContainer mySqlContainer = new ConfluentKafkaContainer("4.0.0");
}

About

Define Mysql, kafka, kafka-connect, elasticsearch, cassandra, SQL Server with testcontainers library

Resources

License

Stars

Watchers

Forks

Packages

No packages published