在我的场景中,我有 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
在此之后验证状态,但我想知道如何以正确的方式做到这一点(即如何确保在杀死演员之后它的观察者收到并处理 Terminated
消息表明它已经死亡)?