Scala 和 Akka - 使用 Akka Testkit 将 actors 作为一个系统进行测试
Scala and Akka - Testing actors as a system with Akka Testkit
在我的 Scala 应用程序中,假设我有 Actor A
和 Actor B
。我想在 ScalaTest 中设计一个测试用例,它允许我向 Actor A
发送消息并查看它发送给 Actor B
的消息,以便查看 A
是否正在正确处理它是数据并将正确的消息发送到 B
。如何测试这个?我花了很长时间才自己把它煮熟……但它似乎大部分时间都有效。
class A extends Actor { ... }
class B extends Actor { ... }
class C(p: TestProbe) extends B {
override def receive = {
LoggingReceive {
case x =>
println(x.toString)
p.ref ! x
}
}
}
case class MsgToB(...)
// Spec class which extends TestKit
"A" should {
"send the right message to B" {
val p = TestProbe()
val a = TestActorRef[A]
val c = TestActorRef(Props(new C(p)))
// Assume A has a reference to C. Not shown here.
a ! msg
// Assert messages
p.expectMsgType[MsgToB]
}
}
这是最好的方法吗?有更好的做法吗?
对我来说,听起来您想要的是孤立地测试参与者 A 的行为。为此,您需要能够控制角色 A 获取其对角色 B 的引用的方式。例如,您可以在角色的构造函数中提供引用:
import akka.actor.{Actor, ActorRef, Props}
class A(refToB: ActorRef) extends Actor { ... }
object A {
def props(refToB: ActorRef): Props = Props(new A(refToB))
}
您可以通过其他方式将对参与者 B 的引用传递给参与者 A,但使用构造函数可以说是最简单的选择。在上面的示例中,我们还提供了一种为演员创建正确的 Props
的方法。
现在您可以控制对 actor B 的引用,您可以在测试中用测试探针替换 actor 引用。
import akka.testkit.TestProbe
// Initialise a test probe
val probe = TestProbe()
// Actor A with reference to actor B replaced with the test probe
val a = system.actorOf(A.props(probe.ref))
// Send a message to actor A
a ! someMessage
// Verify that the probe received a correct response from actor A
p.expectMsgType[MsgToB]
请注意,我使用 TestKit 中的角色系统创建了角色,而不是使用 TestActorRef
。这意味着 actor 消息处理将是异步的而不是同步的。就我个人而言,我发现异步测试风格更合适,因为它更好地代表了演员在生产系统中的表现 运行。 Asynchronous testing is also recommended in the official documentation.
在我的 Scala 应用程序中,假设我有 Actor A
和 Actor B
。我想在 ScalaTest 中设计一个测试用例,它允许我向 Actor A
发送消息并查看它发送给 Actor B
的消息,以便查看 A
是否正在正确处理它是数据并将正确的消息发送到 B
。如何测试这个?我花了很长时间才自己把它煮熟……但它似乎大部分时间都有效。
class A extends Actor { ... }
class B extends Actor { ... }
class C(p: TestProbe) extends B {
override def receive = {
LoggingReceive {
case x =>
println(x.toString)
p.ref ! x
}
}
}
case class MsgToB(...)
// Spec class which extends TestKit
"A" should {
"send the right message to B" {
val p = TestProbe()
val a = TestActorRef[A]
val c = TestActorRef(Props(new C(p)))
// Assume A has a reference to C. Not shown here.
a ! msg
// Assert messages
p.expectMsgType[MsgToB]
}
}
这是最好的方法吗?有更好的做法吗?
对我来说,听起来您想要的是孤立地测试参与者 A 的行为。为此,您需要能够控制角色 A 获取其对角色 B 的引用的方式。例如,您可以在角色的构造函数中提供引用:
import akka.actor.{Actor, ActorRef, Props}
class A(refToB: ActorRef) extends Actor { ... }
object A {
def props(refToB: ActorRef): Props = Props(new A(refToB))
}
您可以通过其他方式将对参与者 B 的引用传递给参与者 A,但使用构造函数可以说是最简单的选择。在上面的示例中,我们还提供了一种为演员创建正确的 Props
的方法。
现在您可以控制对 actor B 的引用,您可以在测试中用测试探针替换 actor 引用。
import akka.testkit.TestProbe
// Initialise a test probe
val probe = TestProbe()
// Actor A with reference to actor B replaced with the test probe
val a = system.actorOf(A.props(probe.ref))
// Send a message to actor A
a ! someMessage
// Verify that the probe received a correct response from actor A
p.expectMsgType[MsgToB]
请注意,我使用 TestKit 中的角色系统创建了角色,而不是使用 TestActorRef
。这意味着 actor 消息处理将是异步的而不是同步的。就我个人而言,我发现异步测试风格更合适,因为它更好地代表了演员在生产系统中的表现 运行。 Asynchronous testing is also recommended in the official documentation.