DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How are you handling the data revolution? We want your take on what's real, what's hype, and what's next in the world of data engineering.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • 6 of the Best API Testing Tools in the Market
  • Mastering Unit Testing and Test-Driven Development in Java
  • Comprehensive Guide to Unit Testing Spring AOP Aspects
  • Improving Java Code Security

Trending

  • Misunderstanding Agile: Bridging The Gap With A Kaizen Mindset
  • Building an IoT Framework: Essential Components for Success
  • Why You Should Move From Monolith to Microservices
  • When Agile Teams Fake Progress: The Hidden Danger of Status Over Substance
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. How to Use Testcontainers With ScyllaDB

How to Use Testcontainers With ScyllaDB

Learn how to use Testcontainers to create lightweight, throwaway instances of ScyllaDB for testing with hands-on example.

By 
Eduard Knezovic user avatar
Eduard Knezovic
·
Guy Shtub user avatar
Guy Shtub
·
Jun. 16, 25 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
1.1K Views

Join the DZone community and get the full member experience.

Join For Free

Setting up a full database environment for every round of integration testing can be time-consuming and complex. This post walks through how to use the Testcontainers library to spin up lightweight, throwaway ScyllaDB instances for testing purposes. We’ll explore a practical example that covers initializing the database and running tests against it.

Testcontainers: A Tool for Integration Testing

You automatically unit test your code and (hopefully) integration test your system…but what about your database? To ensure that the application works as expected, you need to extend beyond unit testing. You also need to automatically test how the units interact with one another and how they interact with external services and systems (message brokers, data stores, and so on). But running those integration tests requires the infrastructure to be configured correctly, with all the components set to the proper state. You also need to confirm that the tests are isolated and don’t produce any side effects or “test pollution.” How do you reduce the pain…and get it all running in your CI/CD process? 

This is where Testcontainers come into play. It is an open source library for throwaway, lightweight instances of databases, message brokers, web browsers, or just about anything that can run in a Docker container. You define your dependencies in code, which makes it well-suited for CI/CD processes. 

When you run your tests, a ScyllaDB container will be created and then deleted. This allows you to test your application against a real instance of the database without having to worry about complex environment configurations. It also ensures that the database setup has no effect on the production environment. 

Using Testcontainers with ScyllaDB offers several practical benefits::

  • It launches Dockerized databases on demand, so you get a fresh environment for every test run.
  • It isolates tests with throwaway containers. There’s no test interference or state leakage since each test gets a pristine database state
  • Tests are fast and realistic, since the container starts in seconds, ScyllaDB responds fast, and actual CQL responses are used.

Tutorial: Building a ScyllaDB Test Step-by-Step

The Testcontainers ScyllaDB integration works with Java,  Go, Python (see example here), and Node.js. Here, we’ll walk through an example of how to use it with Java. The steps described below are applicable to any programming language and its corresponding testing framework. In our specific Java example, we will be using the JUnit 5 testing framework. 

The integration between Testcontainers and ScyllaDB uses Docker. 

Step 1: Configure Your Project Dependencies

Before we begin, make sure you have:

  • Java 21 or newer installed
  • Docker installed and running (required for Testcontainers)
  • Gradle 8

Note: If you are more comfortable with Maven, you can still follow this tutorial, but the setup and test execution steps will be different. 

To verify that Java 21 or newer is installed, run:

java --version


To verify that Docker is installed and running correctly, run:

docker run hello-world


To verify that Gradle 8 or newer is installed, run:

gradle --version


Once you have verified that all of the relevant project dependencies are installed and ready, you can move on to creating a new project.

mkdir testcontainers-scylladb-java
cd testcontainers-scylladb-java
gradle init


A series of prompts will appear. Here are the relevant choices you need to select:

  • Select application
  • Select java
  • Enter Java version: 21 
  • Enter project name: testcontainers-scylladb-java
  • Select application structure: Single application project
  • Select build script DSL: Groovy
  • Select test framework: JUnit Jupiter
  • For "Generate build using new APIs and behavior" select no

After that part is finished, to verify the successful initialization of the new project, run:

./gradlew --version


If everything goes well, you should see a build.gradle file in the app folder. You will need to add the following dependencies in your app/build.gradle file:

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation libs.junit.jupiter

    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    // This dependency is used by the application.
    implementation libs.guava

    // Add the required dependencies for the test
    testImplementation 'org.testcontainers:scylladb:1.20.5'
    testImplementation 'com.scylladb:java-driver-core:4.18.1.0'
    implementation 'ch.qos.logback:logback-classic:1.4.11'
}


Also, to get test report output in the terminal, you will need to add testLogging to app/build.gradle file as well:

tasks.named('test') { // Use JUnit Platform for unit tests. 
useJUnitPlatform()

// Add this testLogging configuration to get 
// the test results in terminal
testLogging { 
    events "passed", "skipped", "failed"
    showStandardStreams = true
    exceptionFormat = 'full' 
    showCauses = true
	}
}


Once you're finished editing the app/build.gradle file, you need to install the dependencies by running this command in the terminal:

./gradlew build


You should see the BUILD SUCCESSFUL output in the terminal. The final preparation step is to create a ScyllaDBExampleTest.java file somewhere in the src/test/java folder. JUnit will find all tests in the src/test/java folder. For example:

touch src/test/java/org/example/ScyllaDBExampleTest.java


Step 2: Launch ScyllaDB in a Container

Once the dependencies are installed and the ScyllaDBExampleTest.java file created, you can copy and paste the code provided below to the ScyllaDBExampleTest.java file. 

This code will start a fresh ScyllaDB instance for every test in this file in the setUp method. To ensure the instance will get shut down after every test, we've created the tearDown method, too.

Java
 
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.scylladb.ScyllaDBContainer;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;

import java.net.InetSocketAddress;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ScyllaDBExampleTest {

    private ScyllaDBContainer scylladb;
    private CqlSession session;

    @BeforeEach
    public void setUp() {
        scylladb = new ScyllaDBContainer("scylladb/scylla:2025.1")
            .withExposedPorts(9042, 19042);
        scylladb.start();
    }

    @AfterEach
    public void tearDown() {
        if (session != null) {
            session.close();
        }
        if (scylladb != null) {
            scylladb.stop();
        }
    }

} 


Step 3: Connect via the Java Driver

You’ll connect to the ScyllaDB container by creating a new session. 

To do so, you’ll need to update your setUp method in the ScyllaDBExampleTest.java file:

Java
 
    @BeforeEach
    public void setUp() {
        scylladb = new ScyllaDBContainer("scylladb/scylla:2025.1")
            .withExposedPorts(9042, 19042);
        scylladb.start();

        // Add the following code to create a connection to ScyllaDB:
        session = CqlSession.builder()
            .addContactPoint(new InetSocketAddress(scylladb.getHost(), scylladb.getMappedPort(9042)))
            .withLocalDatacenter("datacenter1")
            .build();
    }


Step 4: Define Your Schema

Now that you have the code to run ScyllaDB and connect to it, you can use the connection to create the schema for the database. 

Let's define the schema by updating your setUp method in the ScyllaDBExampleTest.java file:

Java
 

    @BeforeEach
    public void setUp() {
        scylladb = new ScyllaDBContainer("scylladb/scylla:2025.1")
            .withExposedPorts(9042, 19042);
        scylladb.start();

        session = CqlSession.builder()
            .addContactPoint(new InetSocketAddress(scylladb.getHost(), scylladb.getMappedPort(9042)))
            .withLocalDatacenter("datacenter1")
            .build();

        // Add the following code to create an example schema
        session.execute("CREATE KEYSPACE IF NOT EXISTS test_keyspace WITH replication = "
            + "{'class': 'NetworkTopologyStrategy', 'datacenter1': 1}");
        session.execute("USE test_keyspace");
        session.execute("CREATE TABLE IF NOT EXISTS users (id UUID PRIMARY KEY, name text, age int)");
    }


Step 5: Insert and Query Data

Once you have prepared the ScyllaDB instance, you can run operations on it. 

To do so, let's add a new method to our ScyllaDBExampleTest class in the ScyllaDBExampleTest.java file:

Java
 
@Test
    public void testScyllaDBOperations() {

        // Insert sample data
        UUID user1Id = UUID.randomUUID();
        UUID user2Id = UUID.randomUUID();

        // Add two new users
        session.execute("INSERT INTO users (id, name, age) VALUES (?, ?, ?)", user1Id, "John Doe", 30);
        session.execute("INSERT INTO users (id, name, age) VALUES (?, ?, ?)", user2Id, "Jane Doe", 27);

        // Retrieve and verify the inserted data
        ResultSet results = session.execute("SELECT * FROM users");
        int count = 0;
        for (Row row : results) {
            assertNotNull(row.getString("name"));
            assertNotNull(row.getInt("age"));
            count++;
        }

        assertEquals(2, count); // Ensure two new users are present 
    }


Step 6: Run and Validate the Test

Your test is now complete and ready to be executed! 

Use the following command to execute the test:

./gradlew clean test --no-daemon


If the execution is successful, you'll notice the container starting in the logs, and the test will pass if the assertions are met. 

Here's an example of what a successful terminal output might look like:

12:05:26.708 [Test worker] DEBUG com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager -- ep-00000012: connection released [route: {}->unix://localhost:2375][total available: 1; route allocated: 1 of 2147483647; total allocated: 1 of 2147483647]
12:05:26.708 [Test worker] DEBUG org.testcontainers.utility.ResourceReaper -- Removed container and associated volume(s): scylladb/scylla:2025.1

ScyllaDBExampleTest > testScyllaDBOperations() PASSED

BUILD SUCCESSFUL in 35s 3 actionable tasks: 3 executed


Full Code Example

The repository for the full code example can be found here.

Level Up: Extending Your ScyllaDB Tests

That only covers the basics. Here are some additional uses you might want to explore on your own:

  • Test schema migrations - Verify that your database evolution scripts work correctly.
  • Simulate multi-node clusters - Use multiple containers to test your application with multi-node and multi-dc  scenarios.
  • Benchmark performance - Measure your application’s throughput under various workloads.
  • Test failure scenarios - Simulate how your application handles network partitions or node failures.
Java
 
// Example: Creating a multi-node cluster
Network network = Network.newNetwork();
    scyllaNode1 = new ScyllaDBContainer("scylladb/scylla:2025.1")
    .withExposedPorts(9042, 19042)
    .withNetwork(network)
    .withNetworkAliases("scylla-node1");

scyllaNode2 = new ScyllaDBContainer("scylladb/scylla:2025.1")
    .withExposedPorts(9042, 19042)
    .withNetwork(network)
    .withNetworkAliases("scylla-node2")
    .withCommand("--seeds=scylla-node1");

scyllaNode1.start();
scyllaNode2.start();


scyllaNode2.stop(); // Example: Node failure simulation


Wrap-Up: Practical ScyllaDB Testing

This approach demonstrates how to run integration tests against a real ScyllaDB instance in Java, without requiring a permanent installation. By simulating realistic database behavior during testing, it helps ensure more reliable production outcomes. You can adapt this method to suit your project’s specific requirements and explore further examples to refine your testing strategy.

Java (programming language) unit test Continuous Integration/Deployment

Published at DZone with permission of Eduard Knezovic. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • 6 of the Best API Testing Tools in the Market
  • Mastering Unit Testing and Test-Driven Development in Java
  • Comprehensive Guide to Unit Testing Spring AOP Aspects
  • Improving Java Code Security

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: