This short tutorial is about getting test classes running for the Cassandra repositories in a Spring boot application. The example provided uses Maven, Spring-data-cassandra and Cassandra-Unit. It also uses Lombok plugin, which is why you won’t see any getters/setters in these beans.
Step 1 : Add dependencies
Add these dependencies in your POM file –
Step 2 : Deciding on alternate port for test Cassandra and creating a corresponding YAML file.
- Download this file : another-cassandra.yaml
- Edit the property “native_transport_port” to the port you need the test (embedded) Cassandra to listen to. The port configured in the file is 9152, which can be used unchanged.
- Add the file to class-path (resources folder).
Step 3 : Write a simple test to check if the embedded Cassandra starts up fine.
[java]
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
import me.prettyprint.hector.api.factory.HFactory;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
public class EmbededCassandraTest {
@Before
public void before() throws TTransportException, IOException, InterruptedException, ConfigurationException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("another-cassandra.yaml", 20000);
}
@Test
public void shouldHaveAnEmbeddedCassandraStartOn9175Port() throws Exception {
Cluster cluster = HFactory.getOrCreateCluster("TestCluster", new CassandraHostConfigurator("localhost:9175"));
assertThat(cluster.getConnectionManager().getActivePools().size(), is(1));
KeyspaceDefinition keyspaceDefinition = cluster.describeKeyspace("system");
assertThat(keyspaceDefinition, notNullValue());
assertThat(keyspaceDefinition.getReplicationFactor(), is(1));
}
@AfterClass
public static void cleanCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
[/java]
Step 4: Create or Edit the application-test.properties for setting the embedded cassandra server settings for the test profile.
Add these properties to application-test.properties. Note that these properties would be picked by the config file we will add in steps further down.
[python]
cassandra.hosts=localhost
cassandra.port=9152
cassandra.keyspace=yourkeyspace
[/python]
Step 5: Spring boot Java Config files
These are the main and test Cassandra config classes for this example –
Main Cassandra Config:
[java]
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
@Configuration
@EnableCassandraRepositories("package.of.your.repositories")
public class CassandraConfig extends AbstractCassandraConfiguration {
@Value("${cassandra.hosts}")
String cassandraHosts;
@Value("${cassandra.port}")
String cassandraPort;
@Value("${cassandra.keyspace}")
String cassandraKeySpace;
@Override
public String getKeyspaceName() {
return cassandraKeySpace;
}
@Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster =
new CassandraClusterFactoryBean();
cluster.setContactPoints(cassandraHosts);
cluster.setPort(Integer.parseInt(cassandraPort));
return cluster;
}
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
}
@Override
public String[] getEntityBasePackages() {
return new String[]{
"package.of.your.domains"};
}
}
[/java]
Test Cassandra Config :
[java]
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ActiveProfiles;
@Configuration
@ActiveProfiles("test")
@PropertySource( {"classpath:application.properties",
"classpath:application-test.properties"})
public class CassandraTestConfig extends CassandraConfig {
}
[/java]
Step 6 : Write the abstract test class
Write this abstract class which the repository test classes can inherit, and which will abstract out the Cassandra configurations :
[java]
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.mycompany.config.CassandraTestConfig;
import lombok.extern.slf4j.XSlf4j;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.springframework.context.annotation.Import;
import java.io.IOException;
import java.util.Properties;
@Import(CassandraTestConfig.class)
@XSlf4j
public abstract class AbstractRepositoryTest {
@BeforeClass
public static void initCassandra() {
try {
Properties prop = new Properties();
prop.load(AbstractRepositoryTest.class.getClassLoader().getResourceAsStream("application-test.properties"));
String cassandraHosts = prop.getProperty("cassandra.hosts");
String cassandraPort = prop.getProperty("cassandra.port");
EmbeddedCassandraServerHelper.startEmbeddedCassandra("another-cassandra.yaml", 20000);
log.info("Connect to embedded db");
Cluster cluster = Cluster.builder().addContactPoints(cassandraHosts).withPort(Integer.parseInt(cassandraPort)).build();
Session session = cluster.connect();
log.info("Initialize keyspace");
session.execute("create keyspace \"mykeyspace\" WITH replication = {‘class’:’SimpleStrategy’, ‘replication_factor’ : 3};");
session.execute("use \"mykeyspace\";");
} catch (TTransportException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Before
public void initTest() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
@AfterClass
public static void cleanCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
[/java]
Step 7 : Domain Object/Entity
[java]
import com.datastax.driver.core.utils.UUIDs;
import lombok.Data;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import java.io.Serializable;
import java.util.UUID;
@Data
@Table(value = "sampleEntity")
public class SampleEntity implements Serializable {
@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED, ordering = Ordering.DESCENDING)
private UUID id;
private String text;
}
[/java]
Step 8 : Repository for ze entity
[java]
import org.springframework.data.cassandra.repository.CassandraRepository;
import java.util.List;
import java.util.UUID;
public interface SampleEntityRepository extends CassandraRepository<SampleEntity> {
SampleEntity findById(UUID id);
}
[/java]
Step 9 : The repository test, gentlemen !
[java]
import com.datastax.driver.core.utils.UUIDs;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import java.util.UUID;
@RunWith(SpringJUnit4ClassRunner.class)
public class SampleEntityRepoTest extends AbstractRepositoryTest {
@Autowired
SampleEntityRepository sampleEntityRepository;
@Test
public void saveOneTest() {
UUID id = UUIDs.timeBased();
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(id);
sampleEntity.setText("Hi");
sampleEntity = sampleEntityRepository.save(sampleEntity);
SampleEntity retrievedSampleEntity = sampleEntityRepository.findById(id);
Assert.assertEquals("Hi", sampleEntity.getText());
}
//other tests…
}
[/java]
Done.
Run the test class to confirm the setup works (or not – which case you are on your own).