簡體   English   中英

Scala和Akka - 使用Akka Testkit測試actor作為系統

[英]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的行為。 為了做到這一點,你需要能夠控制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系統創建了actor,而不是使用TestActorRef 這意味着actor消息處理將是異步的而不是同步的。 就個人而言,我發現異步測試風格更合適,因為它更好地代表了演員在生產系統中的運行方式。 官方文檔中也建議進行異步測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM