Testing Akka with Specs2

Age Mooij

This year I have been working on several systems based on Akka, usually in combination with the excellent Spray framework to build fully asynchronous actor-driven REST servers. All in all this has been going very well but recently I had to reinvent a certain wheel for the third time (on the third project) so I thought it might be good to blog about it so others can benefit from it too.

The problem is very simple: Akka has great unit test support but unfortunately (for me) that support is based on ScalaTest. Now there is nothing wrong with ScalaTest but personally I prefer to write my tests using Specs2 and it turns out that mixing Akka TestKit with Specs2 is a little tricky. The Akka documentation does mention these problems and it gives a brief overview of ways to work around them, but I could not find any current example code online.

I say "current" because one of Akka's main committers, Roland Kuhn, did at one time commit some specs2 example code but unfortunately it got thrown out again later.

Based on that original example, here is my slightly improved and commented version:

import org.specs2.mutable._
import org.specs2.time.NoTimeConversions

import akka.actor._
import akka.testkit._
import akka.util.duration._

/* A tiny class that can be used as a Specs2 'context'. */
abstract class AkkaTestkitSpecs2Support extends TestKit(ActorSystem()) 
                                           with After 
                                           with ImplicitSender {
  // make sure we shut down the actor system after all tests have run
  def after = system.shutdown()
}

/* Both Akka and Specs2 add implicit conversions for adding time-related
   methods to Int. Mix in the Specs2 NoTimeConversions trait to avoid a clash. */
class ExampleSpec extends Specification with NoTimeConversions {
  sequential // forces all tests to be run sequentially

  "A TestKit" should {
    /* for every case where you would normally use "in", use 
       "in new AkkaTestkitSpecs2Support" to create a new 'context'. */
    "work properly with Specs2 unit tests" in new AkkaTestkitSpecs2Support {
        within(1 second) {
          system.actorOf(Props(new Actor {
            def receive = { case x ⇒ sender ! x }
          })) ! "hallo"

          expectMsgType[String] must be equalTo "hallo"
        }
      }
  }
}

Using this little Specs2 context trick bridges the two systems, allowing you to write normal Akka TestKit-based tests but using Specs2 as the test driver and matcher library.

Comments (6)

  1. Lorrin Nelson - Reply

    November 5, 2012 at 11:07 pm

    Thanks so much for posting this! Just what I needed.

  2. Nick McCready - Reply

    December 13, 2012 at 6:25 pm

    Can you explain why the mutable package for specs2 is being used?

    • Age Mooij - Reply

      December 13, 2012 at 6:30 pm

      Purely personal preference. It has nothing to do with Akka or Specs2 in general. I just like the mutable DSL better than the acceptance DSL.
      If you want, you can easily adjust this code for use with immutable acceptance Specifications by changing the import statement. As ar as I know the immutable package also has an After trait so it should work.

  3. Ayose - Reply

    February 2, 2013 at 5:48 pm

    Age, thanks for the post.

    Out of curiosity, why do you prefer Specs2 instead of Scalatest?

    • Age Mooij - Reply

      February 2, 2013 at 6:23 pm

      Purely a personal preference and mostly I just ended up using it because all the Open Source Scala projects I studied at the time were all using it too. I couldn't honestly tell you the difference between the two.

  4. Age Mooij - Reply

    February 2, 2013 at 6:27 pm

    Re-reading this blog now, I notice that I made the sample test use "sequential", which is purely optional and only required if your tests somehow depend on each other.

Add a Comment