Search code examples
spring-bootcassandraspring-boot-testspring-data-cassandratestcontainers

How to use Testcontainers Cassandra with Spring Data for Apache Cassandra?


I develop integration tests for my spring boot application, which works with Cassandra. I use CassandraTemplate for communication with Cassandra.

I have the following config for the database src/test/resources/application.properties:

spring.data.cassandra.contact-points=cassandra-host
spring.data.cassandra.port=9042

To create Testcontainers with Cassandra I try 2 ways:

1) https://niels.nu/blog/2017/spring-cassandra-integration-tests.html

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = {ExampleApplication.class})
@ContextConfiguration(initializers = CounterIntegrationTestContainers.Initializer.class)
@EnableConfigurationProperties
public class CounterIntegrationTestContainers extends CounterIntegrationTest {
    @ClassRule
    public static GenericContainer cassandra =
            new GenericContainer("cassandra:3")
                    .withExposedPorts(9042);

    public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        @Override
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            EnvironmentTestUtils.addEnvironment(
                "testcontainers",
                configurableApplicationContext.getEnvironment(),
                "cassandra.host=" + cassandra.getContainerIpAddress(),
                "cassandra.port=" + cassandra.getMappedPort(9042)
            );
        }
    }
}

2) https://www.baeldung.com/spring-boot-testcontainers-integration-test - in this example we can see postgresql container, but I change it to Cassandra:

public class BaeldungPostgresqlContainer extends PostgreSQLContainer<BaeldungPostgresqlContainer> {
    private static final String IMAGE_VERSION = "postgres:11.1";
    private static BaeldungPostgresqlContainer container;
 
    private BaeldungPostgresqlContainer() {
        super(IMAGE_VERSION);
    }
 
    public static BaeldungPostgresqlContainer getInstance() {
        if (container == null) {
            container = new BaeldungPostgresqlContainer();
        }
        return container;
    }
 
    @Override
    public void start() {
        super.start();
        System.setProperty("DB_URL", container.getJdbcUrl());
        System.setProperty("DB_USERNAME", container.getUsername());
        System.setProperty("DB_PASSWORD", container.getPassword());
    }
 
    @Override
    public void stop() {
        //do nothing, JVM handles shut down
    }
}

So, I have a problem. When I start tests, I got cannot create CassandraTemplate bean, because Cassandra server is not available. it seems, that Spring Data tries to health check Cassandra before creating of test bean of the database server.

Is there any way to use Testcontainers Cassandra with Spring Data for Apache Cassandra?


Solution

  • It seems, that I can run tests with such class:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @ContextConfiguration(
            initializers = CassandraTestPrjApplicationTests.Initializer.class
    )
    public class CassandraTestPrjApplicationTests {
    
        @Test
        public void contextLoads() {
        }
    
        public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
            @Override
            public void initialize(ConfigurableApplicationContext applicationContext) {
                GenericContainer<?> cassandra =
                        new GenericContainer<>("cassandra:3").withExposedPorts(9042);
    
                cassandra.start();
    
                TestPropertyValues.of(
                        "spring.data.cassandra.contact-points=" + cassandra.getContainerIpAddress(),
                        "spring.data.cassandra.port=" + cassandra.getMappedPort(9042)
                ).applyTo(applicationContext);
            }
        }
    }
    
    

    and here is my gradle.build:

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-data-cassandra'
        implementation 'org.springframework.boot:spring-boot-starter-web'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
    
        testCompile "org.testcontainers:testcontainers:1.12.0"
        testCompile "org.testcontainers:cassandra:1.12.0"
    }