gpt4 book ai didi

scala - 发送到 `TestProbe` 的测试消息是否可能在 `TestActor.SetAutoPilot(pilot)` 之前到达

转载 作者:行者123 更新时间:2023-12-03 17:31:34 28 4
gpt4 key购买 nike

Akka Testkit AutoPilot documentation示例表明我们可以将消息发送到 TestProbe调用后立即setAutoPilot :

  probe.setAutoPilot(new TestActor.AutoPilot {
def run(sender: ActorRef, msg: Any): TestActor.AutoPilot =
msg match {
case "stop" ⇒ TestActor.NoAutoPilot
case x ⇒ testActor.tell(x, sender); TestActor.KeepRunning
}
})
//#autopilot
probe.ref ! "hallo"

另一方面 setAutoPilot已实现为向 testActor 发送消息:
def setAutoPilot(pilot: TestActor.AutoPilot): Unit = testActor ! TestActor.SetAutoPilot(pilot)

根据 Akka message receive order guarantees ,没有办法 testActor ( probe.ref ) 接收 "hallo"之前 TestActor.SetAutoPilot(pilot)因为两者都是从同一个来源发送的。

但是,如果我们使用第三个参与者(使用 system.actorOf(...) 创建)发送一个 "hello"probe.ref ,

在某些情况下,它会不会被 probe.ref 收到?之前 TestActor.SetAutoPilot(pilot)因此最终被忽略?

最佳答案

理论上 - 是的,绝对 - 这基本上是你自己对这个问题的回答。实际上,这不太可能,因为另一条消息要经过更长的路径,所以需要发生一些非常不寻常的事情,以便它更早到达。

由于围绕这一点进行理论化不会给出任何可行的答案,因此我编写了一个测试以进行实证观察:

构建.sbt:

libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.5.17"
)

libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-testkit" % "2.5.17",
"org.scalactic" %% "scalactic" % "3.0.5",
"org.scalatest" %% "scalatest" % "3.0.5",
"org.scalacheck" %% "scalacheck" % "1.14.0"
) map (_ % "test")

测试:
import scala.concurrent.duration.DurationInt

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.pattern.ask
import akka.testkit.{TestActor, TestKit, TestProbe}
import akka.util.Timeout
import org.scalatest.{Matchers, PropSpecLike}
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.prop.PropertyChecks

class AutopilotTest extends TestKit(ActorSystem("test"))
with PropSpecLike with PropertyChecks with ScalaFutures with Matchers {

private implicit val askTimeout: Timeout = Timeout(100.millis)

property("Test probe receives autopilot before any other message from same origin") {
forAll(minSuccessful(1000)) { msg: String =>
val probe = TestProbe()
probe.setAutoPilot((sender: ActorRef, msg: Any) => msg match {
case x => sender ! x; TestActor.KeepRunning
})
whenReady((probe.ref ? msg).mapTo[String]) {_ shouldBe msg}
}
}

private class ProxyActor(target: ActorRef) extends Actor {
override def receive: Receive = { case msg: Any => target forward msg }
}
private object ProxyActor { def props(target: ActorRef): Props = Props(new ProxyActor(target)) }

property("Test probe receives autopilot before any other message from other origin") {
// set minSuccessuful to as high as you want, but note that current version takes ~38 seconds on my laptop to run
forAll(minSuccessful(1000)) { msg: String =>
val probe = TestProbe()
val proxy = system.actorOf(ProxyActor.props(probe.ref))
val result = (proxy ? msg).mapTo[String]
probe.setAutoPilot((sender: ActorRef, msg: Any) => msg match {
case x => sender ! x; TestActor.KeepRunning
})
whenReady(result) {_ shouldBe msg}
}
}
}

实际上,我在第二次测试中一直重复 10000 次,并且测试总是通过 - 我还确保如果在向代理发送消息后设置了自动驾驶仪,或者如果 testProbe 没有响应,它会失败。

因此,我想说您所描述的潜在问题要么根本不会发生,要么极不可能发生。这个测试当然是一个非常简单的测试,所以在其他条件下(即阻塞、并行测试执行、CI 等)观察可能会有所不同,但至少它为最常见/最简单的情况提供了一些证据。

关于scala - 发送到 `TestProbe` 的测试消息是否可能在 `TestActor.SetAutoPilot(pilot)` 之前到达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53005628/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com