2013-09-03 11 views
10

下のアクターがheartBeatExpireWorkerとheartBeatAccepterを作成していることを確認するテストを作成しようとしています。ScalaでAkkaアクターが作成されたことをテストするには

最初に、コンテキストの代わりにMockhito模擬やスパイを使用して、私がactorOfを呼び出したことを確認できたと思っていましたが、Akkaのテストフレームワークを破ることなくコンテキストを注入する方法を理解できません。

次に、私は自分が存在することを確認するために、特定のメッセージをワーカーに送信できると考えていました。しかし、Akka TestKitがテスト中の俳優の子供の俳優を作成していないように見えるので、それはうまくいかないと私は思いました。それは、近隣の俳優のために立つことができるTestprobesだけを取ることができます。親HeartBeatPumpWorkerのコンストラクタの子供(例えばHeartBeatAcceptWorker.props)用

class HeartBeatPumpWorker(chatService: ChatService, target: HeartBeatMessageCmd) extends Actor with ActorLogging with 
WorkersReference { 

    val heartBeatInterval = chatService.getHeartBeatInterval 

    val tick = context.system.scheduler.schedule(0 millis, heartBeatInterval millis, self, SendHeartBeat(target)) 

    override def postStop() = tick.cancel() 

    def receive = { 
    case SendHeartBeat(command: HeartBeatMessageCmd) => 
     log.debug("Sending heartbeat") 
     //Send heartbeat to GWT 
     val userTarget = NetworkWorker.buildEventUserTarget(command.getEventCode, command.getUser) 

     val uuid: String = UUID.randomUUID().toString 
     val freshCommand = new HeartBeatMessageCmd(command.getUser, command.getEventCode, uuid, command.getUserSession) 
     networkWorker ! NetworkBroadcast(userTarget, freshCommand) 

     val heartBeatId: String = freshCommand.getUuid 
     //create expirer 
     val heartBeatExpireWorkerRef = context.actorOf(HeartBeatExpireWorker.props(chatService, freshCommand), 
     HeartBeatExpireWorker.name(heartBeatId)) 
     val heartBeatAccepterRef = context 
     .actorOf(HeartBeatAcceptWorker.props(chatService, freshCommand), HeartBeatAcceptWorker.name(heartBeatId)) 

     //record heartbeat 
     chatService.saveSentHeartbeat(heartBeatId, freshCommand.getUserSession, freshCommand.getEventCode, 
      freshCommand.getUser, 
     freshCommand.getTimeCmdGenerated) 
    case _ => 
     log.error("Pumper received unknown message. This shouldn't happen " + sender.path.toString) 
     self ! PoisonPill 
    } 

} 


object HeartBeatPumpWorker { 
    def name(eventCode: String, user: String, sessionId: String) = f"HeartBeatPumpWorker-$eventCode-$user-$sessionId" 

    def path(eventCode: String, user: String, sessionId: String) : String = { 
    EventWorker.Path + "/" + name(eventCode, user, sessionId) 
    } 

    def props(chatService: ChatService, heartBeatMsgCmd: HeartBeatMessageCmd) = { 
    Props(classOf[HeartBeatPumpWorker], chatService, heartBeatMsgCmd) 
    } 
} 

答えて

3

を注入Props。テストから欲しいPropsを渡してください。親が子孫をPropsでインスタンス化するようにします。子供たちとの交流。最後の部分はデータフローに依存します。たとえば、親があなたを子供から隠しているが、それらにメッセージを委任している場合は、メッセージを親に送信します。子供がお互いに話す場合は、テストプローブなどを使用します。

+0

私にはわかりません。私は新しく生成されたheartBeatExpireWorkerRefとheartBeatAccepterRefのパスを定義するために着信引数を使用しているので、receiveメソッドでPropsを定義する必要があります。だから、私は小道具を注射することはできないと思う。 – HappyCoder86

+1

それでは、メッセージを介してそれらを注入する必要があります。最後の手段として、メッセージを介して子の名前を注入し、子を 'ActorSelection'で見てみることができます。それは役に立ちますか? – agilesteel

+0

それはいいようですが、Akka TestKitは俳優が子供の俳優を作ることを許可していますか?これまでに私が見つけたすべての例では、アクターがテストプローブとやりとりすることしかできません。テスト対象のアクターが子アクターを作成するサンプル・テストは見つかりませんでした。私はそのようなサンプルテストをどこで見つけることができるか知っていますか? – HappyCoder86

13

私が現在使っている技術は、アクターの作成をインターセプトしてTestProbesを作成することです。

trait ActorMaker { this: Actor => 
    def makeActor(props: Props) = context.actorOf(props) 
} 

を、代わりにcontext.actorOfのMyActor extends Actor with ActorMakerでそれを使用します。私の俳優で、私は別のActorMakerトレイトで混ぜます。私はすべての作成の俳優とその小道具をキャプチャTestProbeMaker持っ試験では

trait TestProbeMaker { this: Actor => 
    val probes = ListBuffer.empty[(Props, TestProbe)] 
    def makeActor(props: Props) = { val probe = TestProbe() 
    probes += (props -> probe) 
    probe.ref 
    } 
} 

を私はテスト

val actorUnderTest = TestActorRef(Props(new MyActor with TestProbeMaker)) 

中にそれを混ぜて、私は何の俳優正確を主張することができますこの方法作成されます。 probe.expectMsgを使用して、作成したアクターにメッセージを送信することをアサートすることもできます。

プローブにアクセスするにはactorUnderTest.underlyingActor.asInstanceOf[TestProbeMaker]

+0

こんにちは、これはいいですね。しかし、あなたがTestProbeにどのようにアクセスできるかははっきりしていません。テストクラスでは、テスト対象のアクタが作成されたときにフィールドが混在している場合、どのように 'プローブ'リストにアクセスしていますか?コード例があるとは思いませんか? – C0deAttack

+0

@ C0deAttackあなたは 'actorUnderTest.underlyingActor'を使ってプローブのリストにTestProbeMakerにキャストすることができます。 – Andrejs

関連する問題