如何在Spring Data for Apache Cassandra中使用Testcontainers Cassandra?

6
我为我的Spring Boot应用程序开发了集成测试,它与Cassandra一起工作。我使用 CassandraTemplate 与Cassandra进行通信。
我有以下数据库配置 src/test/resources/application.properties:
spring.data.cassandra.contact-points=cassandra-host
spring.data.cassandra.port=9042

我可以翻译这段内容。这是关于如何使用Cassandra创建Testcontainers的两种方法的介绍:

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 - 在这个例子中,我们可以看到使用了postgresql容器,但我将其改为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
    }
}

所以,我有一个问题。当我开始测试时,我遇到了一个问题:无法创建CassandraTemplate bean,因为Cassandra服务器不可用。似乎Spring Data在创建数据库服务器的测试bean之前尝试对Cassandra进行健康检查。

是否有方法可以在Spring Data for Apache Cassandra中使用Testcontainers Cassandra?

3个回答

3

看起来,我可以使用这样的类来运行测试:

@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);
        }
    }
}

这是我的 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"
}

1

你能分享第一次尝试(使用@ClassRule)的日志吗?在我看来,它看起来相当有效。

也许你的测试cassandra还没有启动?默认的testcontainers超时时间为60秒,以便容器的第一个映射网络端口开始监听。检查文档


1
考虑第一种方法,我会从检查测试执行期间运行的容器开始:docker ps,并查看它是否启动(即docker守护程序已启动)并公开了正确的端口。
然后尝试telnet到相应的主机/端口,以确保服务在默认的60秒超时期内启动。
容器似乎已经启动足够了,但如果telnet在此期间无法连接,请尝试将其增加。
 new GenericContainer("cassandra:3")
        .withExposedPorts(9042)
        .withStartupTimeout(Duration.ofMinutes(2));

如果容器暴露了正确的端口,但测试无法连接,请确保在测试中使用了正确的配置参数。我看到了spring.data.cassandra.contact-points的用法,您发送的示例使用了稍有不同的配置,请检查集群初始化代码中是否使用了正确的配置参数(例如"${contact-points}"而不是"${container.host}"或反之亦然)。
另一个选项是在运行测试之前启动Cassandra容器并将其主机和端口硬编码。
希望这能帮到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接