当演员系统关闭时,调度程序会发生什么?

时间:2013-12-29 04:26:14

标签: scala akka

在测试使用actor系统调度程序的actor时,我遇到了一些问题。我曾期望调度程序在每次测试后系统关闭时停止发送预定的消息,但这似乎不会发生。我打算改变我的测试以使用模拟调度程序,但我仍然有几个问题:

  1. 为什么调度程序在其所属的系统关闭后仍然仍在发送消息?

  2. 在运行其他测试之前,是否可以向afterAll添加任何内容以正确关闭调度程序?

  3. 以下是使用Akka 2.1的工作示例:

    import akka.testkit._
    import akka.actor._
    import scala.concurrent._
    import scala.concurrent.duration._
    import ExecutionContext.Implicits.global
    import scala.language.postfixOps
    import org.scalatest._
    
    class MyActor(scheduler : Scheduler) extends Actor{
      def receive = {
        case msg => {
          scheduler.schedule(0 millis, 1000 millis, sender, msg)
        }
      }
    }
    
    class MyActorSpec(_system: ActorSystem) extends TestKit(_system)
      with WordSpecLike
      with ImplicitSender
      with BeforeAndAfterAll{
    
      def this() = this(ActorSystem("TestSystem"))
    
      override def afterAll {
        TestKit.shutdownActorSystem(system)
      }
    
      trait Env{   
        val scheduler = system.scheduler  
        val testRef = TestActorRef(new MyActor(scheduler))
      }
    
      "MyActor" must {
    
        "schedule any received messages to be repeatedly sent back to the sender" in new Env{
          testRef ! "hello"
          expectMsg("hello")
        }
    
        "not send any messages when it hasn't been sent anything" in new Env{
          expectNoMsg
        }
      }
    }
    

    第二次测试失败,因为调度程序仍在从第一次测试发送“hello”消息。

1 个答案:

答案 0 :(得分:0)

我认为您在这里看到的是使用ImplicitSender特征产生的问题。与TestKit一起使用时,有一个发件人ActorRef,其范围在类级别,而不是缩小到每个单独的测试(如Env中的内容)。因为这个隐式发送者是在两个测试中共享的,所以它使得没有得到任何消息的负面断言不起作用。一种可能的解决方法是停止使用ImplicitSender,而是明确将发件人缩小到Env,如下所示:

class MyActorSpec(_system: ActorSystem) extends TestKit(_system)
  with WordSpecLike
  with BeforeAndAfterAll{

  def this() = this(ActorSystem("TestSystem"))

  override def afterAll {
    TestKit.shutdownActorSystem(system)
  }

  trait Env{  
    val senderProbe = TestProbe()
    implicit val sender = senderProbe.ref 
    val scheduler = system.scheduler  
    val testRef = TestActorRef(new MyActor(scheduler))
  }

  "MyActor" must {

    "schedule any received messages to be repeatedly sent back to the sender" in new Env{
      testRef ! "hello"
      senderProbe.expectMsg("hello")
    }

    "not send any messages when it hasn't been sent anything" in new Env{
      senderProbe.expectNoMsg
    }
  }
}