В моем сценарии у меня есть 2 актера:
watchee
(я используюTestProbe
)watcher
(Watcher
завернуто вTestActorRef
, чтобы показать некоторые внутренниеstate
, которые я отслеживаю в своем тесте)
Наблюдатель должен предпринять какие-то действия, когда watchee
умрет.
Вот полный тестовый пример, который я написал до сих пор:
class TempTest(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with FunSuiteLike with Matchers with BeforeAndAfterAll {
def this() = this(ActorSystem("TempTest"))
override def afterAll {
TestKit.shutdownActorSystem(system)
}
class WatcherActor(watchee: ActorRef) extends Actor {
var state = "initial"
context.watch(watchee)
override def receive: Receive = {
case "start" =>
state = "start"
case _: Terminated =>
state = "terminated"
}
}
test("example") {
val watchee = TestProbe()
val watcher = TestActorRef[WatcherActor](Props(new WatcherActor(watchee.ref)))
assert(watcher.underlyingActor.state === "initial")
watcher ! "start" // "start" will be sent and handled by watcher synchronously
assert(watcher.underlyingActor.state === "start")
system.stop(watchee.ref) // will cause Terminated to be sent and handled asynchronously by watcher
Thread.sleep(100) // what is the best way to avoid blocking here?
assert(watcher.underlyingActor.state === "terminated")
}
}
Теперь, поскольку все задействованные акторы используют CallingThreadDispatcher
(все тестовые помощники Akka создаются с использованием реквизита с .withDispatcher(CallingThreadDispatcher.Id)
), я могу с уверенностью предположить, что когда этот оператор возвращает:
watcher ! "start"
... сообщение «старт» уже обработано WatchingActor
, и поэтому я могу делать утверждения на основе watcher.underlyingActor.state
Однако, по моим наблюдениям, когда я останавливаю watchee
с помощью system.stop
или отправляя ему Kill
, сообщение Terminated
, созданное как побочный эффект смерти watchee
, выполняется асинхронно, в другом потоке.
Не-решение состоит в том, чтобы остановить watchee
, заблокировать поток на некоторое время и проверить состояние Watcher
после этого, но я хотел бы знать, как мне сделать это правильно (т.е. как быть уверенным, что после убийства актера его наблюдатель < strong>получено и обработано Terminated
сообщение о смерти)?