如何测试一个发送消息给另一个actor的Akka actor?

10

我正在使用ScalaTest和Akka TestKit编写单元测试和集成测试,针对一个我已经编写的演员,使其仅向另一个演员发送消息而不改变任何内部状态。比如这个例子:

class MyActor extends Actor {
  val anotherActor = context.actorOf(Props[AnotherActor])
  def receive: Receive = {
    case MyMessage => anotherActor ! AnotherMessage
  }
}

我想编写一个测试,确认anotherActorMyActor处理MyMessage的结果下,处理了AnotherMessage。经典的示例是使用TestActorRef来获取基础actor,并检查应该在消息接收时受影响的某些内部状态,如下所示:

val testActorRef = TestActorRef(new MyActor)
"MyActor" should "change some internal state when it receives MyMessage" in {
  testActorRef ! MyMessage
  testActorRef.underlyingActor.someState shouldBe "altered"
}

但在我的情况下,我不关心这种状态。实际上,我想要避免持有任何这样的状态。TestProbe也不是我正在寻找的,因为您仍然需要向正在测试的actor注册TestProbe.ref。就大部分而言,我查看了Akka文档中关于测试的所有示例 (http://doc.akka.io/docs/akka/snapshot/scala/testing.html),但没有找到任何合适的内容。

1个回答

18

可能有几种方法可以做到这一点,我将展示一种在我们有类似测试情况时有效的方法。我仍然认为TestActorRefTestKitTestProbe是可行的方法。考虑以下结构:

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 _ =>
  }
}

问题是您有一个演员实例创建一个子演员,作为您的测试的一部分,您需要确保子演员收到消息,即使在测试中您没有对该子演员的创建进行任何控制。当我们遇到这种情况时,我们会像下面这样简单地处理(使用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 时,我覆盖了创建子 actor 的方法,以提供我的探针。这很粗糙,但也简单且有效。


正是我所需要的!我甚至没有想到可以使用一个方法来创建子Actor,然后覆盖它以插入“TestProbe.ref”。谢谢@cmbaxter。 - nmurthy
如果我们在接收方法内创建了另一个 actor,我们该如何处理? - Gajendra Naidu
1
这个怎么在Java中实现? - Nicola Giancecchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接