Testing against your Cassandra DB with Cassandra Unit

This is something many of us have done already to verify our DAOs: you configure your Spring test context to include an in-memory database such as H2 or HSQLDB, you let Hibernate generate the schema and tables and voilà, you can perform all the tests you need knowing that, as soon as the suite has finished running, the in-memory database will be gone.

This is all well when you are working with a RDBMS database. But what if your storage solution is Cassandra?

Enter the dragon

Enter CassandraUnit, a very useful tool that has been initiated by Jérémy Sevellec. In a few words, CassandraUnit allows you to:

  • Start an embedded Cassandra server for your testing purposes
  • Create your keyspace and tables entirely from an XML, JSON, YAML or CQL script
  • Access to a cluster and a session, both of which can be used for executing CQL scripts in your tests

The project has its own Wiki, which will provide you with some useful, albeit a bit dated documentation on how to integrate and use CassandraUnit in your project.

Thankfully it also provides a series of examples which are very enlightening! I wholeheartedly recommend you to head to the examples to get a quick grasp of all of the possibilities offered to you.

Set it up

What I’m going to describe here is one of the many ways you can integrate and use CassandraUnit into a project.

But first let’s start by doing some setup as usual. In your pom.xml:

That’s all you need. Easy!

Note however that CassandraUnit imports its own versions of cassandra-all and hector-core to work. You can use your own versions of those libraries should you want to, as explained here.

Use it and abuse it

So what now? There’s a few things you can do from here.

You can programmatically start an embedded Cassandra server:

Having done that you can then use a DataLoader or a CQLDataLoader to initialize your test database with the necessary keyspace and tables configuration:

(example from CassandraUnit’s wiki documentation)

CassandraUnit also works well with Spring, as long as you add the cassandra-unit-spring library to the pom.xml:

Your tests’ configuration could then look like this:

(example from CassandraUnit’s wiki documentation)

The way I ended up using it

But the way I ended up integrating CassandraUnit for my tests (so far!) is as follows.

I create a “base” class for my integration tests, as follows:

Line by line:

  • I run my tests using SpringJUnit4ClassRunner.
  • I specify my test Java Configuration by using Spring Boot’s @SpringApplicationConfiguration annotation (by all means, you don’t NEED Spring Boot if you don’t use it!).
  • I expose a CassandraCQLUnit instance as a JUnit rule, using… the @Rule annotation.
  • I build that CassandraCQLUnit in the IntegrationTest classconstructor, specifying the keyspace, the database nodes and port, etc. I also specify the CQL script that will actually build my database. This approach allows me to retain full control on what is set up. For example, I could execute additional scripts to load common test data in the constructor should I need to.
  • Having that CassandraCQLUnit available allows me to access its “cluster” and “session” properties, which I can use to setup some clever test-related helper methods: one method to load additional CQL data sets (which could be called by some tests but not others), one method to truncate all of the tables, etc.
    Yes, I could have used CQLDataLoader to load those additional data sets 😉

Now my tests can extend IntegrationTest and use that CassandraCQLUnit instance to setup a database context, verify the data, etc.

I explicitly separate the code that needs to be tested from the code that tests my classes and methods. I will therefore use that CassandraCQLUnit instance only to setup or verify data, and let my tested methods use their own frameworks (driver-core methods using their own Session object, Spring Data Cassandra, whatever) to do their job.

For example, let’s say I want to test my StuffDAO.insert() method. I will:

  1. Invoke the stuffDAO.insert() method to try to insert some data
  2. Use CassandraCQLUnit to actually test if the data was inserted

Conclusion

Of course this approach is not the only one available, and you are free to disagree and do it your way. Hopefully, CassandraUnit is flexible enough to provide more than one path to the testing Nirvana.

Cheers!

 

2 comments

Comments are closed.