如何使用 Akka TestKit 响应失败的 Ask 模式?
How to respond to an Ask pattern with a failure using Akka TestKit?
我有一个 Akka Actor,它使用 Ask 模式从子 actor 中检索 Future 并对成功和失败进行操作。我不知道如何模仿儿童演员并以失败回应。
代码如下:
import java.util.concurrent.TimeUnit
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.pattern.ask
import akka.testkit.{ImplicitSender, TestKitBase, TestProbe}
import akka.util.Timeout
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import scala.util.{Failure, Success}
class Parent(child: ActorRef) extends Actor {
implicit val timeout = Timeout(5, TimeUnit.SECONDS)
import context.dispatcher
override def receive: Receive = {
case "go" => {
val senderRef = sender()
(child ? "question").mapTo[String] onComplete {
case Success("answer") =>
senderRef ! "child responded with a successful answer"
case Failure(throwable) =>
senderRef ! "child responded with a failure"
}
}
}
}
class SimplifiedProblemSpec extends Specification {
"The Parent Actor" should {
"act on success" in new TestScope {
parent ! "go"
childProbe.expectMsg("question")
childProbe.reply("answer")
expectMsg("child responded with a successful answer")
}
"act on failure" in new TestScope {
parent ! "go"
childProbe.expectMsg("question")
// How to reply with failure?
expectMsg("child responded with a failure")
}
}
}
abstract class TestScope extends Scope with TestKitBase with ImplicitSender {
implicit lazy val system: ActorSystem = ActorSystem()
val childProbe = TestProbe()
val parent = system.actorOf(Props(classOf[Parent], childProbe.ref), "Parent")
}
如有任何帮助,我们将不胜感激。
谢谢
您可以使用 akka.actor
包中的 Status.Failure
个案例 class。来自文档:
This class/message type is preferably used to indicate failure of some operation performed. As an example, it is used to signal failure with AskSupport is used (ask/?).
老实说,我不是 100% 确定这就是您要的,但以防万一您可以尝试这样的操作:
case class FailureMessage(message: String) extends Exception(message)
object MyActor {
def props = Props(classOf[MyActor])
}
class MyActor extends Actor {
override def receive = {
case "cool" => sender ! Status.Success("cool")
case boom => sender ! Status.Failure(FailureMessage("boom"))
}
}
class MyActorSpec extends TestKit(ActorSystem("system")) with ImplicitSender with WordSpecLike with Matchers {
implicit val timeout = Timeout(1 second)
override def afterAll = TestKit.shutdownActorSystem(system)
"system" must {
"return Failure if boom" in {
val actor = system.actorOf(MyActor.props)
actor ! "boom"
expectMsg(Status.Failure(FailureMessage("boom")))
}
}
我有一个 Akka Actor,它使用 Ask 模式从子 actor 中检索 Future 并对成功和失败进行操作。我不知道如何模仿儿童演员并以失败回应。
代码如下:
import java.util.concurrent.TimeUnit
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.pattern.ask
import akka.testkit.{ImplicitSender, TestKitBase, TestProbe}
import akka.util.Timeout
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import scala.util.{Failure, Success}
class Parent(child: ActorRef) extends Actor {
implicit val timeout = Timeout(5, TimeUnit.SECONDS)
import context.dispatcher
override def receive: Receive = {
case "go" => {
val senderRef = sender()
(child ? "question").mapTo[String] onComplete {
case Success("answer") =>
senderRef ! "child responded with a successful answer"
case Failure(throwable) =>
senderRef ! "child responded with a failure"
}
}
}
}
class SimplifiedProblemSpec extends Specification {
"The Parent Actor" should {
"act on success" in new TestScope {
parent ! "go"
childProbe.expectMsg("question")
childProbe.reply("answer")
expectMsg("child responded with a successful answer")
}
"act on failure" in new TestScope {
parent ! "go"
childProbe.expectMsg("question")
// How to reply with failure?
expectMsg("child responded with a failure")
}
}
}
abstract class TestScope extends Scope with TestKitBase with ImplicitSender {
implicit lazy val system: ActorSystem = ActorSystem()
val childProbe = TestProbe()
val parent = system.actorOf(Props(classOf[Parent], childProbe.ref), "Parent")
}
如有任何帮助,我们将不胜感激。
谢谢
您可以使用 akka.actor
包中的 Status.Failure
个案例 class。来自文档:
This class/message type is preferably used to indicate failure of some operation performed. As an example, it is used to signal failure with AskSupport is used (ask/?).
老实说,我不是 100% 确定这就是您要的,但以防万一您可以尝试这样的操作:
case class FailureMessage(message: String) extends Exception(message)
object MyActor {
def props = Props(classOf[MyActor])
}
class MyActor extends Actor {
override def receive = {
case "cool" => sender ! Status.Success("cool")
case boom => sender ! Status.Failure(FailureMessage("boom"))
}
}
class MyActorSpec extends TestKit(ActorSystem("system")) with ImplicitSender with WordSpecLike with Matchers {
implicit val timeout = Timeout(1 second)
override def afterAll = TestKit.shutdownActorSystem(system)
"system" must {
"return Failure if boom" in {
val actor = system.actorOf(MyActor.props)
actor ! "boom"
expectMsg(Status.Failure(FailureMessage("boom")))
}
}