我要测试以下情况:
假设我有一个父演员,它会像这样创建两个子演员。
class A extends Actor {
def getActorOf(props: Props) = {
context.actorOf(props, props.clazz.getTypeName)
}
def receive: Receive = {
case "ping" => {
val bChild = getActorOf(Props[B])
val cChild = getActorOf(Props[C])
Seq(bChild, cChild)
.foreach(child => child ! "ping forwarded")
}
}
}
我想测试一下,如果父母得到'ping'
的话,他会向自己的两个孩子发送'ping forwarded'
消息。
是否可以使用TestKit做到这一点?
答案 0 :(得分:2)
也许是这样?
class TestMe extends A {
val (probeB, probeC) = (TestProbe(), TestProbe())
override def getActorOf(props: Props) = props match {
case Props(_, classOf[B], _) => probeB.ref
case Props(_, classOf[C], _) => probeC.ref
}
}
val fixture = TestActorRef[TestMe](Props[TestMe])
fixture ! "ping"
fixture.underlyingActor.probeB.expectMsg("ping forwarded")
fixture.underlyingActor.probeB.expectMsg("ping forwarded")
我个人希望在可能的情况下采用更“传统”的方法:
trait Forwarder {
def startAndForward[T : ClassTag](message: Any)(implicit context: ActorContext) = {
val actor = context.actorOf(Props[T])
actor ! message
actor
}
}
object Forwarder extends Forwarder
class A(f: Forwarder = Forwarder) extends Actor {
def receive: Receive = {
case m@"ping" =>
f.startAndForward[B]("ping forwarded")
f.startAndForward[C]("ping forwarded")
sender ! "pong"
}
}
现在,您可以通过简单的方式运行测试:
val fwd = mock[Forwarder]
val fixture = context.actorOf(Props(new A(fwd)))
fixture.ask("ping").futureValue shouldBe "pong"
verify(fwd).startAndForward[B](ArgumentMatchers.eq("ping forwarded"))(any, any)
verify(fwd).startAndForward[C](ArgumentMatchers.eq("ping forwarded"))(any, any)