在Akka TestKit中创建TestProbe的时间
我在测试中具有覆盖actorOf的特性:在Akka TestKit中创建TestProbe的时间,akka,akka-testkit,Akka,Akka Testkit,我在测试中具有覆盖actorOf的特性: trait ActorRefFactory { this: Actor => def actorOf(props: Props) = context.actorOf(props) } 我还有worker actor,当收到任何消息时,它会停止self: class WorkerActor extends Actor { override def receive: Actor.Receive = { case _ =>
trait ActorRefFactory {
this: Actor =>
def actorOf(props: Props) = context.actorOf(props)
}
我还有worker actor,当收到任何消息时,它会停止self:
class WorkerActor extends Actor {
override def receive: Actor.Receive = {
case _ => { context.stop(self) }
}
}
我还有一个主演员,他创建演员并让他们排队:
class MasterActor extends Actor with ActorRefFactory {
var workers = Set.empty[ActorRef]
override val supervisorStrategy = SupervisorStrategy.stoppingStrategy
def createWorker() = {
val worker = context watch actorOf(Props(classOf[WorkerActor]))
workers += worker
worker
}
override def receive: Receive = {
case m: String =>
createWorker()
case Terminated(ref) =>
workers -= ref
createWorker()
}
}
这项测试失败了:
class ActorTest(val _system: ActorSystem) extends akka.testkit.TestKit(_system)
with ImplicitSender
with Matchers
with FlatSpecLike {
def this() = this(ActorSystem("test"))
def fixture = new {
val master = TestActorRef(new MasterActor() {
override def actorOf(props: Props) = TestProbe().ref
})
}
it should "NOT FAILED" in {
val f = fixture
f.master ! "create"
f.master ! "create"
f.master.underlyingActor.workers.size shouldBe 2
val worker = f.master.underlyingActor.workers.head
system.stop(worker)
Thread.sleep(100)
f.master.underlyingActor.workers.size shouldBe 2
}
}
在测试中Thread.sleep之后,我给出了错误“1不等于2”。我不知道发生了什么事。但是,如果我猜的话,我可以假设TestProbe()不能及时创建。我能做什么呢?这基本上归结为一个异步性问题,您希望在Akka的单元测试中尝试并避免这个问题。您正确地使用了
TestActorRef
连接到master
参与者的callingreaddispatcher
。但是当您调用system.stop(worker)
时,系统仍然使用默认的异步调度程序,它将在停止并重新创建worker时引入此竞争条件。我所能看到的一致解决此问题的最简单方法是阻止工人这样做:
master.underlyingActor.context.stop(worker)
因为您正在使用master
的context
,而该参与者正在使用callingReadDispatcher
我相信这将消除您看到的asnyc问题。当我尝试它时,它对我有效 不幸的是,它不起作用。例如,如果我在case-Terminated中添加println语句,我就得到了它。这意味着主演员收到了终止消息。@Leonard,为什么你在停止后再次断言大小仍应为2?如果正确接收到终止列表,则列表的大小应从2变为1。你的失败告诉你你的尺寸是1,这与你期望的2不符,但你的期望值实际上应该是1。这并不是那么简单。请看createWorker()方法。当工人被终止时,请创建新工人并将其放入工人集中。@Leonard,我添加了另一个答案。这一个在我尝试它时对我有效。如果我将毒药发送给工人而不是系统。停止(工人),它有效。但我不知道为什么。