Akka Actor 测试:使用 TestProbe 自动回复
Akka Actor Test: Automatic reply with a TestProbe
我正在尝试让测试探测器在收到任何消息时回复确认。
我在测试中编写了以下代码,但它不起作用:
val chgtWriter = new TestProbe(system) {
def receive: Receive = {
case m => println("receive messagereplying with ACK"); sender() ! ACK
}
}
有没有办法做到这一点。实际向测试探针发送消息的参与者肯定 运行 在 TestThread 之外的另一个线程上。您可以在下面看到当前制作的完整测试。
feature("The changeSetActor periodically fetch new change set following a schedule") {
scenario("A ChangeSetActor fetch new changeset from a Fetcher Actor that return a full and an empty ChangeSet"){
Given("a ChangeSetActor with a schedule of fetching a message every 10 seconds, a ChangeFetcher and a ChangeWriter")
val chgtFetcher = TestProbe()
val chgtWriter = new TestProbe(system) {
def receive: Receive = {
case m => println("receive message {} replying with ACK"); sender() ! ACK
}
}
val fromTime = Instant.now().truncatedTo(ChronoUnit.SECONDS)
val chgtActor = system.actorOf(ChangeSetActor.props(chgtWriter.ref, chgtFetcher.ref, fromTime))
When("all are started")
Then("The Change Fetcher should receive at least 3 messages from the ChangeSetActor within 40 seconds")
var changesetSNum = 1
val received = chgtFetcher.receiveWhile( 40 seconds) {
case FetchNewChangeSet(m) => {
println(s"received: FetchNewChangeSet(${m}")
if (changesetSNum == 1) {
chgtFetcher.reply(NewChangeSet(changeSet1))
changesetSNum += 1
}
else
chgtFetcher.reply(NoAvailableChangeSet)
}
}
received.size should be (3)
}
}
changeSetActor 已经过全面测试并且可以正常工作。测试与 ChangeWriter 挂起。它从不在接收方法中接收消息。
EDIT1(关注@Jakko anser)
Auto Pilots如下:
val probe = TestProbe()
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
}
})
虽然到目前为止给出的所有解释都很清楚,但官方示例中令人困惑的是引用"testActor"。这里的 testActor 是谁?那时没有那个名字的变量声明。
您可以使用 Auto Pilots 编写您的测试探针脚本。例如:
import akka.testkit._
val probe = TestProbe()
probe.setAutoPilot(new TestActor.AutoPilot {
def run(sender: ActorRef, msg: Any): TestActor.AutoPilot = {
println("receive messagereplying with ACK")
sender ! ACK
TestActor.KeepRunning
}
})
在上面的示例中,我们设置了一个带有自动消息处理程序 Auto Pilot 的测试探针。当探测器收到消息时,自动驾驶仪将自动触发。在此示例中,自动驾驶仪将打印一条消息并回复发件人。
处理一条消息后,自动驾驶仪可以决定如何处理下一条传入消息。它可以设置不同的自动驾驶仪,重新使用现有的自动驾驶仪 (TestActor.KeepRunning
),或者完全禁用自动驾驶仪 (TestActor.NoAutoPilot
)。在此示例中,将使用同一个自动驾驶仪来处理所有传入消息。
即使自动驾驶仪连接到探测器,您仍然可以像往常一样使用测试探测器断言。
官方文档中的 testActor
指的是您正在针对其编写测试的参与者。例如,在您的情况下,演员可能是分配给值 chgtActor
的 ChangeSetActor
。由于您真正想要做的就是从探测器响应发送者,因此测试探测器自动驾驶仪响应发送者就足够了,而不关心 testActor
.
我正在尝试让测试探测器在收到任何消息时回复确认。
我在测试中编写了以下代码,但它不起作用:
val chgtWriter = new TestProbe(system) {
def receive: Receive = {
case m => println("receive messagereplying with ACK"); sender() ! ACK
}
}
有没有办法做到这一点。实际向测试探针发送消息的参与者肯定 运行 在 TestThread 之外的另一个线程上。您可以在下面看到当前制作的完整测试。
feature("The changeSetActor periodically fetch new change set following a schedule") {
scenario("A ChangeSetActor fetch new changeset from a Fetcher Actor that return a full and an empty ChangeSet"){
Given("a ChangeSetActor with a schedule of fetching a message every 10 seconds, a ChangeFetcher and a ChangeWriter")
val chgtFetcher = TestProbe()
val chgtWriter = new TestProbe(system) {
def receive: Receive = {
case m => println("receive message {} replying with ACK"); sender() ! ACK
}
}
val fromTime = Instant.now().truncatedTo(ChronoUnit.SECONDS)
val chgtActor = system.actorOf(ChangeSetActor.props(chgtWriter.ref, chgtFetcher.ref, fromTime))
When("all are started")
Then("The Change Fetcher should receive at least 3 messages from the ChangeSetActor within 40 seconds")
var changesetSNum = 1
val received = chgtFetcher.receiveWhile( 40 seconds) {
case FetchNewChangeSet(m) => {
println(s"received: FetchNewChangeSet(${m}")
if (changesetSNum == 1) {
chgtFetcher.reply(NewChangeSet(changeSet1))
changesetSNum += 1
}
else
chgtFetcher.reply(NoAvailableChangeSet)
}
}
received.size should be (3)
}
}
changeSetActor 已经过全面测试并且可以正常工作。测试与 ChangeWriter 挂起。它从不在接收方法中接收消息。
EDIT1(关注@Jakko anser)
Auto Pilots如下:
val probe = TestProbe() 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 } })
虽然到目前为止给出的所有解释都很清楚,但官方示例中令人困惑的是引用"testActor"。这里的 testActor 是谁?那时没有那个名字的变量声明。
您可以使用 Auto Pilots 编写您的测试探针脚本。例如:
import akka.testkit._
val probe = TestProbe()
probe.setAutoPilot(new TestActor.AutoPilot {
def run(sender: ActorRef, msg: Any): TestActor.AutoPilot = {
println("receive messagereplying with ACK")
sender ! ACK
TestActor.KeepRunning
}
})
在上面的示例中,我们设置了一个带有自动消息处理程序 Auto Pilot 的测试探针。当探测器收到消息时,自动驾驶仪将自动触发。在此示例中,自动驾驶仪将打印一条消息并回复发件人。
处理一条消息后,自动驾驶仪可以决定如何处理下一条传入消息。它可以设置不同的自动驾驶仪,重新使用现有的自动驾驶仪 (TestActor.KeepRunning
),或者完全禁用自动驾驶仪 (TestActor.NoAutoPilot
)。在此示例中,将使用同一个自动驾驶仪来处理所有传入消息。
即使自动驾驶仪连接到探测器,您仍然可以像往常一样使用测试探测器断言。
官方文档中的 testActor
指的是您正在针对其编写测试的参与者。例如,在您的情况下,演员可能是分配给值 chgtActor
的 ChangeSetActor
。由于您真正想要做的就是从探测器响应发送者,因此测试探测器自动驾驶仪响应发送者就足够了,而不关心 testActor
.