如何測試給定的行爲是否會發送我期望的消息?測試Akka輸入的行爲
說,某些類型的三封郵件,一前一後...
通過定期參與者(非類型化)有是TestProbe從正規阿卡用的方法,如expectedMsg
:
http://doc.akka.io/api/akka/current/index.html#akka.testkit.TestProbe
阿卡式我仍然在撓我的頭。有一種叫做EffectfulActorContext的東西,但我不知道如何使用它。
例
說我寫一個簡單的PingPong
服務,即賦予了許多n
答覆與Pong(n)
n
-times。所以:
-> Ping(2)
Pong(2)
Pong(2)
-> Ping(0)
# nothing
-> Ping(1)
Pong(1)
下面是這種行爲的外觀:
case class Ping(i: Int, replyTo: ActorRef[Pong])
case class Pong(i: Int)
val pingPong: Behavior[Ping] = {
Static {
case Ping(i, replyTo) => (0 until i.max(0)).map(_=> replyTo ! Pong(i))
}
}
我哈克
現在,因爲我無法弄清楚如何使這項工作中,「黑客」,我我現在正在做的是讓演員總是回覆一份回覆列表。所以行爲是:
case class Ping(i: Int, replyTo: ActorRef[List[Pong]])
case class Pong(i: Int)
val pingPong: Behavior[Ping] = {
Static {
case Ping(i, replyTo) => replyTo ! (0 until i.max(0)).map(_=>Pong(i)).toList
}
}
鑑於這種哈克變化,測試人員很容易寫:
package com.test
import akka.typed.AskPattern._
import akka.typed.ScalaDSL._
import akka.typed.{ActorRef, ActorSystem, Behavior, Props}
import akka.util.Timeout
import com.test.PingPong.{Ping, Pong}
import org.scalatest.{FlatSpec, Matchers}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
object PingPongTester {
/* Expect that the given messages arrived in order */
def expectMsgs(i: Int, msgs: List[Pong]) = {
implicit val timeout: Timeout = 5 seconds
val pingPongBe: ActorSystem[Ping] = ActorSystem("pingPongTester", Props(PingPong.pingPong))
val futures: Future[List[Pong]] = pingPongBe ? (Ping(i, _))
for {
pongs <- futures
done <- {
for ((actual, expected) <- pongs.zip(msgs)) {
assert(actual == expected, s"Expected $expected, but received $actual")
}
assert(pongs.size == msgs.size, s"Expected ${msgs.size} messages, but received ${pongs.size}")
pingPongBe.terminate
}
} Await.ready(pingPongBe.whenTerminated, 5 seconds)
}
}
object PingPong {
case class Ping(i: Int, replyTo: ActorRef[List[Pong]])
case class Pong(i: Int)
val pingPong: Behavior[Ping] = {
Static {
case Ping(i, replyTo) => replyTo ! (0 until i.max(0)).map(_=>Pong(i)).toList
}
}
}
class MainSpec extends FlatSpec with Matchers {
"PingPong" should "reply with empty when Pinged with zero" in {
PingPongTester.expectMsgs(0, List.empty)
}
it should "reply once when Pinged with one" in {
PingPongTester.expectMsgs(1, List(Pong(1)))
}
it should "reply with empty when Pinged with negative" in {
PingPongTester.expectMsgs(-1, List.empty)
}
it should "reply with as many pongs as Ping requested" in {
PingPongTester.expectMsgs(5, List(Pong(5), Pong(5), Pong(5), Pong(5), Pong(5)))
}
}
不錯。 「receiveAll」是做什麼的?它是否等待? – drozzy
我更新了代碼,因爲它引用了我的一些代碼,並修復了我用'ctx.getInbox(「pong」)'訪問'Pong'的收件箱的方式。您可以檢查編輯。調用'receiveAll'會給你'Pong'的收件箱中的所有信息,我不確定它是否等待,但我會研究它。 – hajime