2015-09-13 25 views
2

我已經搜索了很多關於這個,但沒有答案。如何基於ActorSelection模擬演員?

我有一個演員 「A」 (用戶/ A)該發送消息 「X」 爲一其他演員 「B」 (用戶/ B)當收到一個消息 「M」。要做到這一點的男演員使用ActorSelection我需要測試,當我送中號一個將收到「X」。

我試着用TestProbe在「user/B」上做這個,但沒有成功。

我也看到一些類似的問題,但每個回答說使用ActorSelection的ActorRef insted。這不是我的選擇,我真的需要使用ActorSelection。

有人有一些想法?

+0

爲什麼你需要使用'ActorSelection'? – Ryan

+1

在我的情況下,我在路徑「/ user/agents/*」上有很多演員,但是這些演員都是volatiI,我沒有爲所有演員「ActorRef」。 另一方面,我有一個爲「/ user/agents/*」發送消息「X」的演員「/ user/xpto」總是收到消息「M」。 我不明白爲什麼如此複雜的模擬阿卡系統上的一些演員。 –

回答

5

簡單的答案:而不是硬編碼選擇的路徑在A使可配置。在測試中,您可以將其指向TestProbe的路徑。

+0

可能值得注意的是,由於TestProbe名稱無法控制(http://doc.akka.io/api/akka/2.3.14/index.html#),因此在當前的Akka發行版中難以做到這一點akka.testkit.TestProbe $) 但是在最新版本的候選版本中,有一個新的'apply'方法來設置名稱:http://doc.akka.io/api/akka/2.4.0-RC2/index。 html#akka.testkit.TestProbe $ – mattinbits

+2

您不需要控制名稱,因爲您可以從'probe.ref.path'獲取它。 –

4

您可以爲您的測試編寫簡單的幫助程序,這些幫助程序與您的演員一樣被命名,但將消息轉發給您的探測器。

假設這是您的設置(簡體):

case object M 
case object X 
class A extends Actor { 
    def receive = { 
    case M => context.system.actorSelection("/user/B") ! X 
    } 
} 

要測試的演員A

你可以寫這樣的「測試框架」爲你的應用程序:

object ForwardActor { 
    def props(to: ActorRef) = Props(new ForwardActor(to)) 
} 

class ForwardActor(to: ActorRef) extends Actor { 
    override def receive = { 
    case x => to forward x 
    } 
} 

def mock(name: String, probe: TestProbe)(implicit system: ActorSystem): Unit = 
    system.actorOf(ForwardActor.props(probe.ref), name) 

然後,你就可以通過簡單地做這種測試,以測試演員A

"A sends X to B after receiving M" in { 
    val probeB = TestProbe() 
    mock("B", probeB) 
    system.actorOf(Props(new A)) ! M 
    probeB expectMsg X 
}