Reading Reactive Messaging Patterns with the Actor Model 03

Testing Actors

  • 2種類のテスト方法が提供されている。Actor内部の状態マシンの振る舞いのテストと、メッセージを使って、外部とのコミュニケーションのテスト。

Unit Testing Actors

  • TestKitをインポートして, TestActorRefを取得して、 実actorを取得する.
1
2
3
import akka.testkit.TestActorRef
val riskManagerRef = TestActorRef[RiskManager]
val riskManager = actorRef.underlyingActor
  • これて、Actor内部のメソッドを直接テストすることができる。

    ※ 内部のメソッドを外部からアクセスさせでもいい。原因はActorは直接作れない、TestActorRefが唯一Actor内部のメソッドを直接アクセスする方法。

  • TestActorRefのもう一つのメリットは、TestActorRefに送るメーセージはメールボックス経由せず、直接receiveに送れる。

ScalaTestを使う場合の例:

1
2
3
4
5
6
7
8
9
10
11
import org.scalatest.FunSuite
import akka.testkit.TestActorRef
class RiskManagerTestSuite extends FunSuite {
val riskManagerRef = TestActorRef[RiskManager]
val riskManager = actorRef.underlyingActor
test("Must have risks when told to calculate.") {
riskManagerRef ! CalculateRisk(Risk(...))
assert(!riskManager.risksToCalculate.isEmpty)
}
...
}

Behavioral Testing Message Processing

  • BDDスタイルのテスト。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.scalatest.BeforeAndAfterAll
import org.scalatest.WordSpecLike
import org.scalatest.matchers.Matchers
import akka.testkit.ImplicitSender
import akka.testkit.TestKit
class RiskCalculatorSpec(testSystem: ActorSystem)
extends TestKit(testSystem)
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {
// there is an implicit class argument
def this() = this(ActorSystem("RiskCalculatorSpec"))
override def afterAll {
TestKit.shutdownActorSystem(system)
}

"A RiskCalculator" must {
"confirm that a risk calculation request is in progress" in {
val riskCalculator = system.actorOf(Props[RiskCalculator])
riskCalculator ! CalculateRisk(Risk(...))
expectMsg(CalculatingRisk(...))
}
}