【问题标题】:Sending a message to a TestProbe() fails sometimes with ActorInitializationException有时会因 ActorInitializationException 向 TestProbe() 发送消息失败
【发布时间】:2023-12-31 19:44:01
【问题描述】:

我有一些零星的测试失败,并且很难找出原因。我有很多演员可以参加我想要测试的工作。在测试开始时,我传入了一个从 TestProbe() 获得的演员参考。稍后这组参与者做一些工作并将结果发送到给定的测试探针参与者参考。然后我用 TestProbe() 检查结果:

class MyCaseSpec extends Spec with ShouldMatchers{
    describe("The Thingy"){
        it("should work"){
            val eventListener = TestProbe()

            val myStuffUnderTest = Actor.actorOf(new ComplexActor(eventListener.ref)).start();
            myStuffUnderTest ! "Start"

            val eventMessage = eventListener.receiveOne(10.seconds).asInstanceOf[SomeEventMessage]
            eventMessage.data should be ("Result")
        }

    }
}

现在有时测试会失败。当我查看堆栈跟踪时,我看到在向测试探针参与者发送消息时收到了“ActorInitializationException”。但是,我在任何时候都不会停止 TestProbe 演员。

这是一个例外:

[akka:event-driven:dispatcher:global-11] [LocalActorRef] Actor has not been started, you need to invoke 'actor.start()' before using it
akka.actor.ActorInitializationException: Actor has not been started, you need to invoke 'actor.start()' before using it
[Gamlor-Laptop_c15fdca0-219e-11e1-9579-001b7744104e]
at akka.actor.ScalaActorRef$class.$bang(ActorRef.scala:1399)
at akka.actor.LocalActorRef.$bang(ActorRef.scala:605)
at akka.mobile.client.RemoteMessaging$RemoteMessagingSupervision$$anonfun$receive$1.apply(RemoteMessaging.scala:125)
at akka.mobile.client.RemoteMessaging$RemoteMessagingSupervision$$anonfun$receive$1.apply(RemoteMessaging.scala:121)
at akka.actor.Actor$class.apply(Actor.scala:545)
....

我想知道我是否遗漏了一些明显的东西,还是我犯了一个微妙的错误?或者也许我的代码中真的出了问题而我看不到它?

我正在使用 Akka 1.2。

Vitors 评论更新。在第 125 行,我使用 ! 操作符向演员发送消息。现在在测试设置中,这就是 TestProbe 演员参考。而且我不明白为什么有时 TestProbe 演员似乎停止了。

   protected def receive = {
      case msg: MaximumNumberOfRestartsWithinTimeRangeReached => {
        val lastException = msg.getLastExceptionCausingRestart
        faultHandling ! ConnectionError(lastException, messages.toList, self) // < Line 125. The faultHandling is the TestProbe actor
        become({
            // Change to failure-state behavior
          }
    // Snip

无论如何,我目前正在尝试进一步隔离问题。感谢您的任何提示/想法。

【问题讨论】:

  • 你为什么不包括最有趣的部分?在 akka.mobile.client.RemoteMessaging$RemoteMessagingSupervision$$anonfun$receive$1.apply(RemoteMessaging.scala:125)
  • 在 125 处,我向我的 TestProbe() actor 发送了一条消息:我无法弄清楚为什么 test-probe actor 有时没有运行并且我得到了异常。

标签: scala akka


【解决方案1】:

你不是在这里开始你的演员。我不确定为什么您的测试有时会起作用。上面的代码需要用.start()修改以下行

val myStuffUnderTest = Actor.actorOf(new ComplexActor(eventListener.ref)).start();

【讨论】:

  • 哦。这是上面示例中的错误。在实际测试中它是启动的。修正了这个例子。
【解决方案2】:

好的,几乎可以肯定找到了问题 =)。 TestProbes 确实有超时:当 5 秒后没有任何反应时,它们会自行停止。

不幸的是,现在测试只需要 5 秒多一点时间:在那段时间里,测试探针可能会自行停止,这会导致测试失败。

修复很简单,增加 TestProbe 的超时时间:

  val errorHandler = ignoreConnectionMsgProbe()
  errorHandler.setTestActorTimeout(20.seconds)

【讨论】:

  • 是的,这正是发生的事情以及处理它的方法(您也可以使用Duration.Inf 完全禁用它)。我还发现这令人困惑(几周前花了我几个小时来归咎于实际原因),我应该知道的。无论如何,这个问题在 2.0 中消失了,所有参与者在测试后有序关闭,没有任何超时(如果你停止 ActorSystem,就是这样)。