【问题标题】:How to use Testcontainers Cassandra with Spring Data for Apache Cassandra?如何使用 Testcontainers Cassandra 和 Spring Data for Apache Cassandra?
【发布时间】:2019-12-23 00:54:26
【问题描述】:

我为我的 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 进行健康检查。

有什么方法可以使用 Testcontainers Cassandra 和 Spring Data for Apache Cassandra?

【问题讨论】:

    标签: spring-boot cassandra spring-boot-test spring-data-cassandra testcontainers


    【解决方案1】:

    您能否分享第一次尝试的日志(使用@ClassRule)?这对我来说看起来很有效。

    也许您的测试 cassandra 还没有开始?容器的第一个映射网络端口开始侦听的默认测试容器超时为 60 秒。 check the docs

    【讨论】:

      【解决方案2】:

      考虑到第一种方法,我首先检查在测试执行期间正在运行的容器:docker ps 并查看它是否启动(即 docker 守护程序已启动)并公开正确的端口。
      然后尝试telnet到相应的主机/端口,以确保服务在the default 60 seconds timeout period期间启动。
      好像容器启动就够了,但是如果telnet在这期间没有连接,试试像这样增加

       new GenericContainer("cassandra:3")
              .withExposedPorts(9042)
              .withStartupTimeout(Duration.ofMinutes(2));
      

      如果容器暴露了正确的端口,但测试没有连接到它, 确保在测试中使用正确的配置参数。我看到spring.data.cassandra.contact-points 的用法,您发送的示例使用bit different configuration,请检查您的集群初始化代码中的配置参数是否正确(例如"${contact-points}" 而不是"${container.host}",反之亦然)。

      检查您的集成测试逻辑是否按预期工作的另一个选项(并且 testcontainers 配置有问题)是启动 Cassandra 容器并在运行测试之前对其主机和端口进行硬编码。

      希望这会有所帮助。

      【讨论】:

        【解决方案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"
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-03-08
          • 2017-05-13
          • 2020-01-19
          • 2020-12-19
          • 2014-10-11
          • 1970-01-01
          • 2018-08-23
          • 2020-10-31
          相关资源
          最近更新 更多