在测试Akka演员时,如何验证发送给自己的消息?

时间:2012-09-18 17:59:33

标签: scala testing akka

我有一个类似于以下Actor中的Actor。

case class SupervisingActor() extends Actor {

    protected val processRouter = //round robin router to remote workers
    override def receive = {
        case StartProcessing => { //sent from main or someplace else
            for (some specified number of process actions ){
                processRouter ! WorkInstructions
            }
        }
        case ProcessResults(resultDetails) => {  //sent from the remote workers when they complete their work
            //do something with the results
            if(all of the results have been received){
                //*********************
                self ! EndProcess  //This is the line in question
                //*********************
            }
        }
        case EndProcess {
            //do some reporting
            //shutdown the ActorSystem
        }
    }
}

}

如何在测试中验证EndProcess消息是否已发送给self?

我正在使用scalatest 2.0.M4,Akka 2.0.3和Scala 1.9.2。

3 个答案:

答案 0 :(得分:12)

发送给自己的演员非常关注该演员如何执行特定功能的详细信息,因此我宁愿测试该消息的效果,而不是该消息是否已被传递。我认为发送给self与在经典OOP中对象上使用私有帮助器方法相同:你也不测试是否调用了那个,你测试最后是否发生了正确的事情。

作为旁注:您可以实现自己的消息队列类型(请参阅https://doc.akka.io/docs/akka/snapshot/mailboxes.html#creating-your-own-mailbox-type)并允许检查或跟踪消息发送。这种方法的优点在于它可以纯粹通过配置插入到被测试的演员中。

答案 1 :(得分:0)

过去,我已经覆盖了!的实现,以便我可以添加调试/日志记录。只需打电话给超级!当你完成了,并且要特别注意不要做任何会引发异常的事情。

答案 2 :(得分:0)

我和FSM演员有同样的问题。我尝试按照接受的答案设置自定义邮箱,但几分钟没有让它正常工作。我还尝试按照另一个答案覆盖tell运算符,但这是不可能的,因为self是最终的val。最后我换了:

 self ! whatever

使用:

 sendToSelf(whatever)

并将该方法添加到actor中:

// test can override this
protected def sendToSelf(msg: Any) {
  self ! msg
}

然后在测试中覆盖了捕获自发消息的方法并将其发送回fsm以完成工作:

  @transient var sent: Seq[Any] = Seq.empty

  val fsm = TestFSMRef(new MyActor(x,yz) {
    override def sendToSelf(msg: Any) {
      sent = sent :+ msg
    }
  })

  // yes this is clunky but it works
  var wait = 100
  while( sent.isEmpty && wait > 0 ){
    Thread.sleep(10)
    wait = wait - 10
  }

  fsm ! sent.head