在测试使用actor系统调度程序的actor时,我遇到了一些问题。我曾期望调度程序在每次测试后系统关闭时停止发送预定的消息,但这似乎不会发生。我打算改变我的测试以使用模拟调度程序,但我仍然有几个问题:
为什么调度程序在其所属的系统关闭后仍然仍在发送消息?
在运行其他测试之前,是否可以向afterAll添加任何内容以正确关闭调度程序?
以下是使用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”消息。
答案 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
}
}
}