Как можно проверять сообщения, отправленные на себя, доставляются при тестировании аккских актеров?
У меня есть Актер, который похож на следующий Актер в функции.
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 отправлено самому себе в тесте?
Я использую scalatest 2.0.M4, Akka 2.0.3 и Scala 1.9.2.
Ответы
Ответ 1
Актер, отправляющий сам по себе, представляет собой очень подробную информацию о том, как этот актер выполняет определенную функцию, поэтому я предпочел бы проверить эффект этого сообщения, чем то, было ли это сообщение доставлено. Id утверждают, что отправка в себя - это то же самое, что и частный метод-помощник на объекте в классическом ООП: вы также не проверяете, вызван ли этот вызов, вы проверяете, произошло ли в конечном итоге.
В качестве побочного примечания: вы можете реализовать свой собственный тип очереди сообщений (см. https://doc.akka.io/docs/akka/snapshot/mailboxes.html#creating-your-own-mailbox-type) и иметь возможность проверки или отслеживания отправки сообщений. Красота этого подхода заключается в том, что он может быть вставлен исключительно по конфигурации в тестируемый актер.
Ответ 2
В прошлом я переопределил реализацию для !
, чтобы добавить debug/logging. Просто позвоните супер! когда вы закончите, и будьте осторожны, чтобы не делать ничего, что могло бы вызвать исключение.
Ответ 3
У меня была такая же проблема с актером FSM. Я попытался настроить пользовательский почтовый ящик в соответствии с принятым ответом, но через несколько минут он не работал. Я также попытался переопределить оператор tell в соответствии с другим ответом, но это невозможно, так как self является окончательным значением val. В конце концов я просто заменил:
self ! whatever
с:
sendToSelf(whatever)
и добавил этот метод в актер как:
// 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