Using ScalaCheck with Akka and Specs2
I spent some time this weekend playing around with Akka. It took me a while to get it to work nicely with ScalaCheck and Specs2.
My first attempt was to make the test create a new Akka TestKit
:
def e1 = new TestKit(system) with Scope with ImplicitSender {
within(1 second) {
system.actorOf(Props(new Actor {
def receive = { case x ⇒ sender ! x }
})) ! "hallo"
expectMsgType[String] must be equalTo "hallo"
}
}
But I couldn’t get ScalaCheck to work inside of the Scope
. Instead,
I had to move the TestKit
up to the Specification class. Then I
could make a big trait with everything I needed:
trait AkkaScalaCheck extends
Specification with
NoTimeConversions with
ScalaCheck with
ImplicitSender { self: TestKit => }
Specs2 will automatically run tests in parallel (awesome feature) but that broke my tests because actors were sending responses to queries from other tests.
I just had to tell Specs2 to run tests sequentially:
testOptions in Test += Tests.Argument("sequential")
I tried just inserting sequential
in the Specification but that
didn’t work for me. I’ll try to narrow down why soon.
The final code looks something like this:
import org.specs2.{ Specification, ScalaCheck }
import org.specs2.specification.Step
import org.specs2.time.NoTimeConversions
import akka.actor.{ Props, ActorSystem }
import akka.testkit.{ TestKit, ImplicitSender }
import akka.util.duration._
trait AkkaScalaCheck extends
Specification with
NoTimeConversions with
ScalaCheck with
ImplicitSender { self: TestKit => }
class MySpec(system: ActorSystem) extends TestKit(system) with AkkaScalaCheck {
def this() = this(ActorSystem("MySpec"))
def is =
"Test should" ^
p ^
"pass" ! e1 ^
Step(system.shutdown()) ^ end
val ping = system.actorOf(Props[Ping])
def message[A] = receiveOne(1 second).asInstanceOf[A]
def e1 = check((a: Int) => {
ping ! a
message must be equalTo a
})
}