通过system.actorOf获得的ActorRef是否等于此actor中的self?

时间:2015-07-13 11:56:00

标签: scala akka akka-testkit

我设计的一个演员应该发送它的' actorRef到prestart上的另一个演员:

class MyActor(notifier: ActorRef) extends Actor {
  override def preStart(): Unit = {
    notifier ! Register(self)
  }
  ...
}

case class Register(actor: ActorRef)

然后我为这个演员写了一个规范:

class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
                  with ImplicitSender 
                  with WordSpecLike 
                  with Matchers 
                  with BeforeAndAfterAll {

  "MyActor" should {
     val notifier = TestProbe()
     "register itself in notifier" in {
         val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
         notifier.expectMsg(Register(myActor))
     }
  }
}

当我运行测试时,它失败并显示以下消息:assertion failed: expected Register(Actor[akka://MyActorSpec/user/$b#1849780829]), found Register(Actor[akka://MyActorSpec/user/$a#1143150267])

因此,似乎在MyActor中通过self获得的ActorRef不等于在我的测试中通过system.actorOf获得的ActorRef。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

以下代码对我来说很合适(测试通过):

class MyActor(notifier: ActorRef) extends Actor {
  override def preStart(): Unit = {
    notifier ! Register(self)
  }

  override def receive: Receive = {
    case _ =>
  }
}

case class Register(actor: ActorRef)

class MyActorSpec extends TestKit(ActorSystem("MyActorSpec")) with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
  "MyActor" should {
    val notifier = TestProbe()
    "register itself in notifier" in {
      val myActor = system.actorOf(Props(new MyActor(notifier.ref)))
      notifier.expectMsg(Register(myActor))
    }
  }
}

答案 1 :(得分:1)

您理想情况下发布的代码甚至不应该在以下位置编译:

val myActor = system.actorOf(Props(classOf[MyActor], notifier))

因为构造函数需要一个我们没有传递的ActorRef。但纠正它,它的确有效:

class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {

  "MyActor" should {
    val notifier = TestProbe()
    "register itself in notifier" in {
      val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
      notifier.expectMsg(Register(myActor))
    }
  }
}

有一秒钟,为了确保由于ActorProbe没有发生特殊的魔法,我在下面写了一个简单的老演员班。

object Prac {
  def main(args: Array[String]) {
    val system = ActorSystem("HelloSystem")
    val myActor = system.actorOf(Props(classOf[MainActor]))
  }

}

class MyActor(notifier: ActorRef) extends Actor {

  override def preStart(): Unit = {
    notifier ! Register(self)
  }

  override def receive: Receive = {
    case x => println("My Actor ->"+x)
  }
}

case class Register(actor: ActorRef)

class MainActor extends Actor{

  val actor = context.actorOf(Props(classOf[MyActor], self))

  override def receive = {
    case Register(x) =>
      println(actor == x)
      context.system.shutdown()
  }
}

并打印true。所以你的程序没有任何问题。

答案 2 :(得分:0)

我已经弄清楚了。这是因为我在几个测试用例中使用了共享的TestProbe,其中我创建了MyActor的不同实例。

class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
                  with ImplicitSender 
                  with WordSpecLike 
                  with Matchers 
                  with BeforeAndAfterAll {

  "MyActor" should {
     val notifier = TestProbe()
     "register itself in notifier" in {
         val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
         notifier.expectMsg(Register(myActor))
     }
     "do some useful work" in {
         val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
         ....
     }
  }
}

相反,为每个测试用例使用一个新的TestProbe实例有帮助。

class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
                  with ImplicitSender 
                  with WordSpecLike 
                  with Matchers 
                  with BeforeAndAfterAll {

  "MyActor" should {
     "register itself in notifier" in {
         val notifier = TestProbe()
         val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
         notifier.expectMsg(Register(myActor))
     }
     "do some useful work" in {
         val notifier = TestProbe()
         val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
         ....
     }
  }
}

无论如何,多亏了所有证明对于单个测试用例它运行良好。