2014-09-22 54 views
5

我有以下几点:阿卡测试主管错误处理

class Supervisor(dataProvider: DatabaseClientProvider) extends Actor { 
    val writer = context.actorOf(Props(classOf[Child], dataProvider.get)) 
    def receive: Receive = { 
    case Msg => writer forward msg 
    } 
    override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 100) { 
    case e: ConnectionException => Resume 
    } 
} 

class Child(db: DatabaseClient) extends Actor { 
    def receive: Receive = { 
    case msg:Msg => db.write(text) 
    } 
} 

我想上面的代码进行单元测试基本上我想确保,当出现异常,我们还在恢复处理,你可以看到下面。问题是主管没有发现任何异常。测试下面的代码的最佳方法是什么?

"resume handling messages when exception occurs" in { 

    // Given 
    val msg1 = Msg("Some msg1") 
    val msg2 = Msg("Some msg2") 

    //Throw an exception when attempting to write msg1 
    val databaseClient = mock[DatabaseClient] 
    when(databaseClient.write(msg1.text).thenThrow(ConnectionException("Error!")) 

    val dataProvider = mock[DatabaseClientProvider] 
    when(dataProvider.get).thenReturn(databaseClient) 

    val supervisor = system.actorOf(Props(new Supervisor(dataProvider))) 

    // When 
    intercept[ConnectionException] { 
     supervisor ! msg1 
    } 

    // When 
    supervisor ! msg2 

    // Then 
    verify(databaseClient.write("Some msg"), times(2)) 
} 

回答

8

要当一个孩子抛出你必须测试supervisorStrategy异常测试主管的行为。使用TestActorRef,你可以访问supervisorStrategy的部分功能,并断言给定Exception导致预期Directive

val supervisor = TestActorRef[Supervisor](Props(new Supervisor(dataProvider))) 
val strategy = supervisor.underlyingActor.supervisorStrategy.decider 
strategy(ConnectionException("boom")) should be (Resume) 
+0

我希望AKKA以更直观的方式命名这些方法! – Mayumi 2014-09-25 20:44:48

+0

“决定者”含糊不清,但我没有看到他们改变了一个名字(打破向后兼容),以求可读性的小改变。好吧 – 2014-09-25 21:05:40

0

我敢打赌,这个问题是在这个方法:

def receive: Receive = { 
    case Msg => writer forward Msg 
    } 

“消息的情况下”被类型类消息引发,而不是由类消息的实例。像这样的东西应该工作:

def receive: Receive = { 
    case msg:Msg => writer forward msg 
    } 
+0

我输入错的计算器,那不是我的问题。我在问如何测试孩子的策略处理。 – Mayumi 2014-09-25 03:30:45