「Google」を嘲笑しないため、統合内部テストを行うのは奇妙な方法のように思えます。したがって、統合外部テストに似ており、同期TestActorRef
はここにはあまり適合しません。スプレー内のスレッドを制御する要件も非常にトリッキーです。ただし、http-request で本当に必要な場合は、可能です。一般的に、以下のように複数のディスパッチャを設定する必要がありますapplication.conf
:
- "manager-dispatcher" (Http.scala から) をディスパッチする
IO(Http) ? req
- "host-connector-dispatcher" で
HttpHostConnector
(またはProxyHttpHostConnector
) 実際にリクエストをディスパッチする
- 「設定グループディスパッチャ」
Http.Connect
それらはすべて、スプレーのドキュメントの構成セクションに記載されています。そして、それらはすべて「akka.actor.default-dispatcher」( Dispatchersを参照) を指しているため、これを変更することですべてを変更できます。
ここでの問題は、スレッドの呼び出しが実際にスレッドであるとは限らないため、テストにはあまり役に立たないことです。一部のアクターがメッセージに応答してハンドラーを登録する場合を想像してみてください。
//somewhere in spray...
case r@Request => registerHandler(() => {
...
sender ! response
})
応答は別のスレッドから送信される可能性があるため、response.value
まだNone
最新の状態である可能性があります。実際には、応答は、テストのスレッドから独立して、基礎となるソケット ライブラリのリッスン スレッドから送信されます。簡単に言うと、リクエストは 1 つの (あなたの) スレッドで送信されますが、レスポンスは別のスレッドで受信されます。
本当にここでブロックする必要がある場合は、そのようなコード サンプル ( などIO(Http) ? HttpRequest
) を移動して、テスト内で便利な方法でそれらをモックすることをお勧めします。そのようにSmtng:
trait AskGoogle {
def okeyGoogle = IO(Http) ? HttpRequest(GET, Uri("http://www.google.com"))).mapTo[HttpResponse]
}
trait AskGoogleMock extends AskGoogle {
def okeyGoogle = Await.result(super.okeyGoogle, timeout)
}
class Processor extends Actor with AskGoogle {
override def receive = {
case Msg(n) =>
val response = okeyGoogle
println(response.value)
}
}
val realActor = system.actorOf(Props[Processor])
val mockedActor = TestActorRef[Processor with AskGoogleMock]
ところで、カスタム アクターに対してIO(HTTP)
別のモックを作成することもできます。これによりTestActorRef
、外部の要求が実行されます。大きなプロジェクトの場合は、最小限のコード変更で済みます。