JUnit中使用EmbeddedCassandra创建Keyspace失败求助
解决EmbeddedCassandra加载CQL时提示Keyspace不存在的问题
我看了你遇到的问题:用cassandra-unit-spring 3.1.1.0做JUnit测试时,明明已经在代码里创建了keyspace,但加载表结构的CQL时还是提示keyspace不存在。这个问题大概率是创建keyspace后Cassandra的schema未完成同步,或者session上下文切换未生效导致的,下面给你几个可行的解决方案:
方案1:创建keyspace后等待schema同步
哪怕是单节点的嵌入式Cassandra实例,创建keyspace后也需要一点时间完成schema的传播。你可以在创建keyspace后添加一段等待逻辑,确保keyspace真正可用:
@BeforeClass public static void setup() { try { EmbeddedCassandraServerHelper.startEmbeddedCassandra("another-cassandra.yaml", 20000); Cluster cluster = Cluster.builder().addContactPoints("localhost").withPort(9000).build(); Session session = cluster.connect(); // 用IF NOT EXISTS避免重复创建报错 session.execute("CREATE KEYSPACE IF NOT EXISTS mosaickeyspace WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1}"); // 等待keyspace生效:循环查询元数据直到keyspace存在 Metadata metadata = cluster.getMetadata(); while (metadata.getKeyspace("mosaickeyspace") == null) { Thread.sleep(100); metadata = cluster.getMetadata(); } // 直接连接到目标keyspace,规避USE语句的上下文问题 session = cluster.connect("mosaickeyspace"); final CQLDataLoader cqlDataLoader = new CQLDataLoader(session); cqlDataLoader.load(new ClassPathCQLDataSet("create-table.cql", false, true, "mosaickeyspace")); } catch(Exception excp) { LOGGER.info("Error in setup ", excp); excp.printStackTrace(); } }
方案2:确保CQL文件中的表语句指定keyspace
检查你的create-table.cql文件,确保所有表创建语句都明确绑定keyspace,比如:
CREATE TABLE mosaickeyspace.user ( id UUID PRIMARY KEY, name TEXT );
这样即使session上下文没有切换到目标keyspace,CQL语句也能直接找到对应的keyspace。
方案3:优化注解驱动的配置
如果你之前用@EmbeddedCassandra没生效,可能是注解的配套配置没做全。试试这种方式,让cassandra-unit自动处理keyspace和CQL的加载顺序:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {TestConfig.class}) @EmbeddedCassandra(timeout = 20000, config = "another-cassandra.yaml") @TestExecutionListeners({CassandraUnitTestExecutionListener.class, DependencyInjectionTestExecutionListener.class}) public class UserServiceTest { @Autowired private Session session; @BeforeClass public static void setupKeyspace() { // 或者直接把CREATE KEYSPACE语句放到create-table.cql的最开头 } @Test public void testUserService() { // 你的测试逻辑 } }
把CREATE KEYSPACE IF NOT EXISTS ...语句放到create-table.cql的第一行,cassandra-unit会按顺序执行CQL,先创建keyspace再建表,从根源避免找不到keyspace的问题。
另外补充几个小细节:
- 用
CREATE KEYSPACE IF NOT EXISTS代替直接创建,避免重复执行测试时的报错; - 不要用
System.out.println(excp.getStackTrace()),直接调用excp.printStackTrace()输出的异常信息更完整; - 确认
another-cassandra.yaml配置文件里的native_transport_port是9000,和代码中的连接端口一致。
内容的提问来源于stack exchange,提问作者Dhruv Saksena
相关产品推荐
相关产品推荐

