在Akka TestKit中创建TestProbe的时间

时间:2014-10-22 13:10:46

标签: akka akka-testkit

我在测试中有覆盖actorOf的特性:

trait ActorRefFactory {
  this: Actor =>

  def actorOf(props: Props) = context.actorOf(props)
}

我有工作演员,在收到任何讯息后会自动停止:

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()无法在时间内创建。我该怎么办?

1 个答案:

答案 0 :(得分:2)

这基本上归结为你想在Akka的单元测试中试图避免的异步性问题。您正确使用TestActorRef来加入CallingThreadDispatcher演员的master。但是当你调用system.stop(worker)时,system仍然使用默认的异步调度程序,它会在停止然后重新创建一个worker时引入这种竞争条件。我能够始终如一地找到解决这个问题的最简单方法就是像这样阻止工人:

master.underlyingActor.context.stop(worker)

因为您正在使用context master并且该演员正在使用CallingThreadDispatcher我相信这会删除您所看到的asnyc问题。当我尝试它时,它对我有用。