Sunday, July 29, 2012

Unit/Integration testing with Maven and Embedded Cassandra

I've been using Cassandra on my current project. I was able to utilize embedded cassandra feature of cassandra-unit to create a testable application without the need of installing/configuring Cassandra on developer boxes.

I've created a sample application showing setup/code skeleton I used. Project is available on github here. It requires java 5 or higher (tested it with 7) and maven 3.x installed.

Required dependencies and configuration files
1. Cassandra-unit (see pom snippets below)


        
            com.netflix.astyanax
            astyanax
            ${astyanax.version}
            
             .....
            
        
        
            org.cassandraunit
            cassandra-unit
            ${cassandra.unit.version}
            test
            
             ....
            
        
      
Note: Pull project here for the full dependency list.

3. cassandra.yaml - Configuration used to start embedded version of Cassandra. Check out file in the project for configuration details. Note that all the directories required by Cassandra configured in this file are children of target directory.

4. dataset.json - Keyspace and column family definition

Test case setup and layout
Although, I'm not a big fan of using inheritance, I found that defining base class with common functionality and having tests extend it to be the easiest, cleanest approach in this case.

BaseCassandraTest.java (fragments)
   .....
    @BeforeClass
    public static void startCassandra()
            throws IOException, TTransportException,
            ConfigurationException, InterruptedException
    {
        EmbeddedCassandraServerHelper
        .startEmbeddedCassandra("cassandra.yaml");
    }

    @Before
    public void setUp() throws IOException, 
     TTransportException, ConfigurationException, InterruptedException
    {
        DataLoader dataLoader = new DataLoader("TestCluster", 
         "localhost:9272");
        dataLoader.load(new ClassPathJsonDataSet("dataset.json"));

        AstyanaxContext context = 
         new AstyanaxContext.Builder().forCluster("TestCluster")
                .forKeyspace("test_keyspace")
                .withAstyanaxConfiguration(
                 new AstyanaxConfigurationImpl()
                 .setDiscoveryType(NodeDiscoveryType.NONE))
                .withConnectionPoolConfiguration(
                        new ConnectionPoolConfigurationImpl(
                        "testConnectionPool").setPort(9272)
                                .setMaxConnsPerHost(1)
                                .setSeeds("localhost:9272"))
                .withConnectionPoolMonitor(
                 new CountingConnectionPoolMonitor())
                .buildKeyspace(ThriftFamilyFactory.getInstance());

        context.start();
        keyspace = context.getEntity();
        cassandraAccessor = 
         new CassandraAccessor(new ObjectMapper(), keyspace);
    }

    @After
    public void clearCassandra()
    {
        EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
    }

    @AfterClass
    public static void stopCassandra()
    {
        EmbeddedCassandraServerHelper.stopEmbeddedCassandra();
    }
   ...
Class listed above defines lifecycle for each Cassandra test. Embedded Cassandra is started/stoped before, after class, and keyspace is tore down, cleaned and recreated for each test.

This setup has worked pretty well. Alternate approach would be to have a test cluster setup and just configure client to connect to the cluster during tests.

3 comments:

  1. hi Piotr, nice post, very useful and to the point. I am using Cassandra 1.1.4 so I had to comment out the line 117 in the .yaml file.
    # sliced_buffer_size_in_kb: 64
    This config param was removed in Cassandra 1.1.0. Otherwise it worked like a charm and a good example of how to go about constructing a DAO for cassandra,
    br, Declan

    ReplyDelete
  2. Howdy! What a terrific looking blog you own! Did you apply all the settings to your blog by yourself?

    ReplyDelete
  3. Thank you, I am glad you like it.There is a template you setup somewhere. I think I got the info from there: http://stackoverflow.com/questions/679189/formatting-code-snippets-for-blogging-on-blogger
    Piotr

    ReplyDelete