Spring Boot集成Elasticsearch测试抛出Cassandra异常求助
问题分析与调试解决方案
你碰到的核心问题很明确:当测试类PerformanceReportingIntTest继承AbstractElasticSearchTest时,Spring加载完整应用上下文时会尝试初始化Cassandra相关Bean,但你的Elasticsearch测试类并没有启动嵌入式Cassandra,导致DatabaseDescriptor.getNativeTransportPort抛出空指针——而那些继承AbstractCassandraTest的测试能正常运行,正是因为这个抽象类包含了嵌入式Cassandra的启动逻辑。
下面给你几个可行的调试和解决方向:
1. 合并嵌入式服务的启动逻辑(推荐,适合同时需要两者的测试)
Java不支持多继承,所以你可以创建一个新的抽象测试类,把Cassandra和Elasticsearch的启动/停止逻辑整合在一起:
@ActiveProfiles(JHipsterConstants.SPRING_PROFILE_TEST) public abstract class AbstractCassandraElasticTest extends AbstractCassandraTest { private static EmbeddedElastic embeddedElastic; @BeforeClass public static void startEmbeddedServices() throws Exception { // 先启动Cassandra(复用AbstractCassandraTest的逻辑) // 假设AbstractCassandraTest有对应的静态启动方法,比如startEmbeddedCassandra() AbstractCassandraTest.startEmbeddedCassandra(); // 再启动Elasticsearch embeddedElastic = EmbeddedElastic.builder().withElasticVersion("6.6.1") .withSetting(PopularProperties.TRANSPORT_TCP_PORT, 9350) .withSetting(PopularProperties.CLUSTER_NAME, "my_cluster") .withStartTimeout(2, TimeUnit.MINUTES) .withIndex("cars", IndexSettings.builder() .withType("car", getSystemResourceAsStream()) .build()) .build() .start(); } private static InputStream getSystemResourceAsStream() throws FileNotFoundException { ClassLoader classloader = Thread.currentThread().getContextClassLoader(); return classloader.getResourceAsStream("config/elasticsearch/car-mapping.json"); } @AfterClass public static void stopEmbeddedServices() { // 先停止Elasticsearch if (embeddedElastic != null) { embeddedElastic.stop(); } // 再停止Cassandra(复用AbstractCassandraTest的停止逻辑) AbstractCassandraTest.stopEmbeddedCassandra(); } }
然后让你的测试类继承这个新的抽象类:
@RunWith(SpringRunner.class) @SpringBootTest(classes = PrimecastApp.class) public class PerformanceReportingIntTest extends AbstractCassandraElasticTest { @Test public void test() { // 你的测试逻辑 } }
2. 排除Cassandra配置(如果测试不需要Cassandra)
如果这个测试其实不需要和Cassandra交互,你可以直接在@SpringBootTest中排除Cassandra相关的自动配置类,避免Spring尝试初始化Cassandra Bean:
@RunWith(SpringRunner.class) @SpringBootTest( classes = PrimecastApp.class, exclude = {CassandraAutoConfiguration.class, CassandraTestConfiguration.class} ) public class PerformanceReportingIntTest extends AbstractElasticSearchTest { @Test public void test() { } }
注意:这里要根据你项目中实际的Cassandra配置类调整排除的类名,确保完全禁用Cassandra的自动初始化。
3. 调试验证步骤
- 先单独运行继承
AbstractCassandraTest的现有测试,确认嵌入式Cassandra能正常启动,排除Cassandra本身的问题; - 写一个极简测试类,继承
AbstractElasticSearchTest并排除Cassandra配置,验证Elasticsearch嵌入式实例能正常启动; - 合并逻辑后,检查测试上下文启动时的日志,确认Cassandra和Elasticsearch都成功初始化,没有端口冲突或启动超时;
- 核对
application-test.yml中的Cassandra配置,确保指向的是嵌入式实例的端口(而非外部服务)。
额外注意事项
- 确保嵌入式Cassandra和Elasticsearch的端口(比如Cassandra的9042,Elasticsearch的9350)不会和本地已运行的服务冲突;
- 静态初始化方法的执行顺序:父类的
@BeforeClass会先执行,所以继承AbstractCassandraTest后,Cassandra会先启动,再启动Elasticsearch,这个顺序是合理的; - 资源清理:
@AfterClass要确保两个服务都能正常停止,避免残留进程占用端口。
内容的提问来源于stack exchange,提问作者knowledgeseeker
相关产品推荐
相关产品推荐

