Neuigkeiten von trion.
Immer gut informiert.

Cassandra 4 mit Testcontainers in Spring Boot

Cassandra 4 ist ein lang erwartetes Release der Cassandra Datenbank. Dabei hat sich nicht nur einiges in der Datenbank selbst geändert, sondern auch die Java Libraries für den Zugriff haben einige API Änderungen erfahren.
In dem Zuge sind viele andere Projekte aktuell noch nicht soweit, gute Unterstützung für Cassandra 4 zu bieten. Spring Boot bzw. Spring Data Cassandra ist jedoch bereits soweit, dass aktuelle Treiber genutzt werden. Dort stellt sich die Frage, wie das Thema Unit Test bzw. Integrationstest mit Cassandra 4 umgesetzt werden kann.

Es gibt für Cassandra einige Unit-Test Ansätze, die zum Teil einen Embedded-Cassandra-Cluster starten können. Mit neueren Cassandra-Versionen, speziell Version 4, und aktuellen JDK-Versionen funktioniert das jedoch nicht. Abhilfe kann da das Testcontainers-Projekt schaffen - Cassandra wird dann einfach als (Docker) Container gestartet und kann ganz normal verwendet werden. Testcontainers selbst bietet für Cassandra in Version 3.x expliziten Support, für Cassandra 4 ist das jedoch auch schnell durch einen GenericContainer konfiguriert.

Als Beispiel dient eine Spring Boot 2.6 Anwendung mit Spring Data Cassandra als zusätzliche Abhängigkeit. Zunächst muss Testcontainers als Abhängigkeit hinzugefügt werden, hier mit Maven gezeigt.

Maven Abhängigkeit für Testcontainers
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.16.2</version>
</dependency>
<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>junit-jupiter</artifactId>
   <version>1.16.2</version>
</dependency>

Für Spring Boot kann dann ein Test angelegt werden, der duch @Testcontainers die Integration mit dem Testcontainers Framework herstellt. Da der Test auf einem Cassandra Schema arbeiten soll und Cassandra als leere Instanz für den Test bereitgestellt wird, kann durch das Spring Boot-Property spring.data.cassandra.schema-action=create ein Schema erzeugt werden.
Dazu muss Cassandra selbst als @Container ebenfalls definiert werden. Als Timeout sollte - je nach Umgebung - ein Wert im Minutenbereich gewählt werden.

Nun fehlt lediglich noch der Cassandra Keyspace. Im Beispiel wird eine entsprechende Konfiguration als @TestConfiguration definiert, die zusätzlich zur regulären Spring @Configuration herangezogen wird.

Damit Spring Data Cassandra die Verbindung zu der per Container bereitgestellten Cassandra-Instanz herstellen kann, ist es am einfachsten, eine @DynamicPropertySource zu verwenden und damit die Cassandra Contactpoints zu konfigurieren.

Grundgerüst für einen Spring Boot Cassandra Test mit Testcontainers
@SpringBootTest(properties = "spring.data.cassandra.schema-action=create")
@Testcontainers
public class TestcontainersCassandraTest
{
    @Container
    public static GenericContainer cassandra = new GenericContainer("cassandra:4")
       .withExposedPorts(9042)
       .waitingFor(
          new LogMessageWaitStrategy().withRegEx(".*Starting listening for CQL clients.*")
             .withStartupTimeout(Duration.of(2, ChronoUnit.MINUTES)));

    @DynamicPropertySource
    static void configure(DynamicPropertyRegistry registry)
    {
        registry.add("spring.data.cassandra.contact-points", () ->
           String.format("%s:%s", cassandra.getContainerIpAddress(), cassandra.getMappedPort(9042)));
    }

    @TestConfiguration
    public static class CassandraConfiguration extends AbstractCassandraConfiguration
    {
        @Override
        protected List<CreateKeyspaceSpecification> getKeyspaceCreations()
        {
                var specification = CreateKeyspaceSpecification
                .createKeyspace("demo").ifNotExists()
                .with(KeyspaceOption.DURABLE_WRITES, true)
                .withSimpleReplication();
                return List.of(specification);
        }

        @Override
        protected String getKeyspaceName()
        {
                return "demo";
        }
   }

   // ...  test methods ...
}

Mit diesem Grundgerüst können nun Tests durchgeführt werden. Da der Aufbau des Cassandra Testclusters relativ zeitaufwändig ist, sollten die Integrationstests entsprechend gebündelt werden.




Zu den Themen Cassandra, Docker und Kubernetes bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels