首页 文章

Scala和Akka - 使用Akka Testkit测试actor作为系统

提问于
浏览
3

在我的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]
  }
}

这是最好的方法吗?有更好的做法吗?

1 回答

  • 1

    对我而言,听起来你想要的是孤立地测试演员A的行为 . 为了做到这一点,你需要能够控制actor A如何获得对actor B的引用 . 例如,你可以在actor的构造函数中提供引用:

    import akka.actor.{Actor, ActorRef, Props}
    
    class A(refToB: ActorRef) extends Actor { ... }
    
    object A {
      def props(refToB: ActorRef): Props = Props(new A(refToB))
    }
    

    有其他方法可以将对actor B的引用传递给actor A,但使用构造函数可以说是最简单的选择 . 在上面的示例中,我们还提供了一种为actor创建正确的 Props 的方法 .

    现在您可以控制对actor B的引用,您可以在测试中将actor引用替换为test probe .

    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中的actor系统而不是使用 TestActorRef 创建了actor . 这意味着actor消息处理将是异步的而不是同步的 . 就个人而言,我发现异步测试风格更合适,因为它更好地代表了演员在 生产环境 系统中的运行方式 . Asynchronous testing is also recommended in the official documentation .

相关问题