BBL Testcontainers - Carrefour - 2020

La préhistoire

La préhistoire... et ses reliquats

Naissance des Testcontainers

Testcontainers sont les instances lègeres et jétables

Les Testcontainers est une extention de JUnit

@Testcontainers  // <- ajouter extention
class ExampleTestWithElasticsearch {

    @Container  // <- déclarer un ou plusieurs containeurs
    ElasticsearchContainer container =
            new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");

    @Test
    public void exampleTest() {
        container.getHttpHostAddress();  // <- récuperer le port exposé et s'y connecter
        //...
    }
}

Les scopes des Testcontainers

Scopes - container partagé

@Testcontainers
class ExampleTestWithElasticsearch {

    @Container  // <- containeur partagé
    static ElasticsearchContainer container =
            new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");

    RestHighLevelClient client;

    @BeforeEach
    public void init() {
        /* We get Elasticsearch host-port */
        String httpHostAddress = container.getHttpHostAddress();

        RestClientBuilder clientBuilder = RestClient.builder(HttpHost.create(httpHostAddress));
        client = new RestHighLevelClient(clientBuilder);
    }

    @Test
    public void exampleTest1() { /* ... */ }

    @Test
    public void exampleTest2() { /* ... */ }
}

Scopes - container singleton

/* Attention! Don't add annotation @Testcontainers nor @Container */
abstract class AbstractElasticsearchTest {
    static ElasticsearchContainer container =
            new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");
    static {
        container.start();
    }
}

class ExampleTestWithElasticsearch extends AbstractElasticsearchTest {
    RestHighLevelClient client;

    @BeforeEach
    public void init() {
        /* We get Elasticsearch host-port */
        String httpHostAddress = container.getHttpHostAddress();

        RestClientBuilder clientBuilder = RestClient.builder(HttpHost.create(httpHostAddress));
        client = new RestHighLevelClient(clientBuilder);
    }

    @Test
    public void exampleTest() { /* ... */ }
}

Scopes - contrôle manuel du cycle de vie

ElasticsearchContainer container =
        new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");

container.start();
//...
container.stop();

ou

try (ElasticsearchContainer container =
             new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4")) {
    container.start();
    // Stop is called by try-with-resources
}

Ryuk

Ryuk

Modules

Modules - Elasticsearch

ElasticsearchContainer container =
        new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");
        

Modules - Kafka

KafkaContainer kafkaContainer = new KafkaContainer();
kafkaContainer.start();

/* Get Kafka bootstrap servers for client */
kafkaContainer.getBootstrapServers();

ou avec Zookeeper externe

KafkaContainer kafkaContainer = new KafkaContainer().withExternalZookeeper("localhost:2181");

Container custom

@Container
GenericContainer redis = new GenericContainer<>("redis:5.0.3-alpine")
        .withExposedPorts(6379);
        

Spring Boot + Testcontainers

Configuration Spring Boot

# application.yml
spring:
  data:
    elasticsearch:
      cluster-name: my-cluster
      cluster-nodes: localhost:9200
      

Strig Boot test + Testcontainers

@SpringBootTest
@Testcontainers
public class CatalogTaskletIntegrationTest {

    @Container
    static ElasticsearchContainer elasticsearch = 
        new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4")
            .withEnv("cluster.name", "my-cluster");

    @DynamicPropertySource
    static void elasticsearchProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.elasticsearch.cluster-name", () -> "my-cluster");
        registry.add("spring.data.elasticsearch.cluster-nodes", elasticsearch::getHttpHostAddress);
    }
}

Merci pour votre attention !

(Je sais, ma présentation est moche)