我将ScalaTest与Akka TestKit结合使用,为我编写的actor编写单元测试和集成测试,以简单地将消息发送给另一个actor而不改变任何内部状态。以这个为例:
class MyActor extends Actor {
val anotherActor = context.actorOf(Props[AnotherActor])
def receive: Receive = {
case MyMessage => anotherActor ! AnotherMessage
}
}
我想编写一个测试,以确认由于anotherActor
处理AnotherMessage
而导致的MyActor
处理MyMessage
。典型的示例是使用TestActorRef
来获取基础参与者,并检查一些在收到消息后应该受到影响的内部状态,如下所示:
val testActorRef = TestActorRef(new MyActor)
"MyActor" should "change some internal state when it receives MyMessage" in {
testActorRef ! MyMessage
testActorRef.underlyingActor.someState shouldBe "altered"
}
但就我而言,我不在乎这种状态。实际上,我想避免保持任何此类状态。TestProbe
也不是我想要的,因为您仍然必须向TestProbe.ref
接受测试的演员注册。在大多数情况下,我查看了Akka测试文档(http://doc.akka.io/docs/akka/snapshot/scala/testing.html)中的所有示例,但没有找到合适的示例。
可能有几种方法可以做到这一点,我将向您展示在我们进行类似测试时可以工作的一种方法。我仍然认为TestActorRef
,TestKit
并且TestProbe
是要走的路。考虑以下结构:
case object MyMessage
case object AnotherMessage
class MyActor extends Actor {
val anotherActor = createAnother
def receive: Receive = {
case MyMessage => anotherActor ! AnotherMessage
}
def createAnother = context.actorOf(Props[AnotherActor])
}
class AnotherActor extends Actor{
def receive = {
case _ =>
}
}
问题是您有一个actor实例创建一个子actor,并且作为测试的一部分,即使您在测试中没有任何控制,也需要确保该子得到一条消息。遇到这种情况时,我们将执行以下类似的简单操作(使用specs2完成,但应该能够在ScalaTest中创建类似的内容):
import akka.actor._
import akka.testkit._
import org.specs2.mutable.SpecificationLike
import org.specs2.runner.JUnitRunner
import org.junit.runner.RunWith
class MessageSendingSpec extends TestKit(ActorSystem("test")) with SpecificationLike{
val probe = TestProbe()
val myActor = TestActorRef(new MyActor{
override def createAnother = probe.ref
})
"Sending MyMessage to an instance of MyActor" should{
"pass AnotherMessage to the child AnotherActor" in {
myActor ! MyMessage
probe.expectMsg(AnotherMessage)
success
}
}
}
关键是在创建要测试的actor时,我将覆盖创建子级的方法以提供我的探针。它很粗糙,而且简单有效。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句