2016-11-29 45 views
2

我有一個演員系統,大致是這樣的:如何讓我的本地演員更具可測性?

class LocalActor extends Actor { 

    // create the remote actor 
    val remoteActor = context.actorSelection("akka.tcp://[email protected]:2552/user/RemoteActor") 

    def receive = { 
    case foo: String => remoteActor ! s"foo = ${foo}" 
    case bar: Int => remoteActor ! s"bar = ${bar}" 
    case _ => remoteActor ! "No clue..." 
    } 
} 

我想重構它這樣remoteActor的TCP/IP不固定的。最簡單的變化是顯式傳遞給構造函數:

class LocalActor(TcpIp: String) extends Actor { 

    val remoteActor = context.actorSelection(TcpIp) 
    // ... 
} 

但我擔心這可能導致了TCP/IP地址已在使用的情況下的問題。這是很有道理的,以我的選擇是演員(或引用或類似)傳遞給構造函數 - 有一個地道的方式阿卡做到這一點?

我有點困惑,因爲remoteActor的類型是akka.actor.ActorSelection,我可能預計它是ActorActorRef

幸運的是,這個遠程演員只與sender互動,所以它的方式很好;但當地演員仍然很棘手。

如果上面我的想法是不是一個好的,什麼是傳統的辦法,使之更加通用和可測試性?實現這一

回答

3

一種方法是直接傳遞關於你的演員類:

object LocalActor { 
    def prop(remoteActor: ActorRef) = Props(new LocalActor(remoteActor)) 
} 

class LocalActor(remoteActor: ActorRef) extends Actor { 
    def receive = { 
    case foo: String => remoteActor ! s"foo = ${foo}" 
    case bar: Int => remoteActor ! s"bar = ${bar}" 
    case _ => remoteActor ! "No clue..." 
    } 
} 

那麼無論你創建你的LocalActor您還可以通過解決actorSelection創建參考remoteActor

val system = ActorSystem("yourSystem") 
implicit val resolveTimeout = Timeout(5 seconds) 
val remoteActor = Await.result(system.actorSelection("akka.tcp://[email protected]:2552/user/RemoteActor").resolveOne(), resolveTimeout.duration) 
val localActor = system.actorOf(LocalActor.props(remoteActor), "LocalActor") 

然後進行測試,您只需要注入一個TestProbe

val testProbe = TestProbe() 
val testingLocalActor = system.actorOf(LocalActor.props(testProbe.ref)) 
val testString = "TEST" 
testingLocalActor ! testString 
testProbe.expectMsg(s"foo = $testString") 
+0

'TestProbe'是輝煌!乾杯。 – erip