Akka演员的状态没有得到适当的监控

时间:2014-05-30 13:45:47

标签: scala akka actor

使用 .underlyingActor 可以监控Akka演员的状态

在下面的示例中,使用整数计数器存在 ActorWithState 。计数器递增和递减的过程由 ActorWithStateTest 测试。增量步骤总是通过。但是,计数器的减少似乎不起作用,因为第二个断言总是失败。错误消息如下。 出了什么问题?

[此测试的错误讯息]

[info] ActorWithStateTest
[info] - should validate counter incrementation and decrementation *** FAILED ***
[info]   1 did not equal 0, Expected counter to be 0 after 'Terminated' message

[有柜台的演员]

        object ActorWithState {
          case class Inc;
        }

        class ActorWithState(snooper: ActorRef) extends Actor with ActorLogging {
           var counter = 0

           def receive = {
               case Inc             => counter += 1 
               case Terminated(ref) => counter -= 1
           }
        }

[ActorTest将测试计数器的行为]

class ActorWithStateTest extends TestKit(ActorSystem("SimpleTestSpec")) {

  "Test" should {
    "validate counter incrementation and decrementation" in {

      val aws = TestActorRef(Props(classOf[ActorWithState], testActor), name = "aws")
      val awsA: ActorWithState = aws.underlyingActor

      // tell aws to increment its counter
      aws ! ActorWithState.Inc

      // this assert always passes
      assert(awsA.counter == 1, ", Expected counter to be 1 after 'Inc' message")

      // triggers a 'Terminated' message being sent to aws
      val tp = TestProbe()
      aws    watch tp.ref
      system stop  tp.ref

      // [EDIT] the following assert passes if some - time consuming - processing is added here

      // the following assert does NOT pass, WHY?          
      assert(awsA.counter == 0, ", Expected counter to be 0 after 'Terminated' message")
    }
  }

[akka-actor:2.3.2,akka-testkit:2.3.2,scalatest:2.0]

1 个答案:

答案 0 :(得分:3)

正如我的评论中提到的,你的问题源于停止演员异步。您的断言发生在Terminated消息击中您正在测试的演员之前。解决此问题的一种快速而肮脏的方法是引入另一个探测器,该探测器还侦听已终止的事件并首先执行断言。这将等到第二个观察者收到终止后,这意味着你的演员也收到了已终止的事件,你可以执行你的断言。这对我有用:

  val tp = TestProbe()
  val tp2 = TestProbe()
  aws    watch tp.ref
  tp2    watch tp.ref
  system stop  tp.ref
  tp2.expectTerminated(tp.ref)

  assert(awsA.counter == 0, ", Expected counter to be 0 after 'Terminated' message")