如何将 Testcontainers Cassandra 与 Spring 数据一起用于 Apache Cassandra?
How to use Testcontainers Cassandra with Spring Data for Apache Cassandra?
我为我的 spring 引导应用程序开发集成测试,它与 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 一起使用吗?
你能分享第一次尝试的日志吗(使用@ClassRule)?它看起来对我来说很有效。
也许你的测试卡桑德拉还没有成功启动?容器的第一个映射网络端口开始侦听的默认 testcontainers 超时为 60 秒。 check the docs
考虑到第一种方法,我首先在测试执行期间检查 运行 的容器:docker ps
并查看它是否启动(即 docker 守护进程已启动) 并公开正确的端口。
然后尝试telnet
到对应的host/port确保服务在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 容器并在 运行 测试之前对其主机和端口进行硬编码。
希望对您有所帮助。
看来,我可以 运行 测试 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);
}
}
}
这是我的 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"
}
我为我的 spring 引导应用程序开发集成测试,它与 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 一起使用吗?
你能分享第一次尝试的日志吗(使用@ClassRule)?它看起来对我来说很有效。
也许你的测试卡桑德拉还没有成功启动?容器的第一个映射网络端口开始侦听的默认 testcontainers 超时为 60 秒。 check the docs
考虑到第一种方法,我首先在测试执行期间检查 运行 的容器:docker ps
并查看它是否启动(即 docker 守护进程已启动) 并公开正确的端口。
然后尝试telnet
到对应的host/port确保服务在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 容器并在 运行 测试之前对其主机和端口进行硬编码。
希望对您有所帮助。
看来,我可以 运行 测试 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);
}
}
}
这是我的 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"
}