在Akka演员测试中忽略偶尔的DeathWatchNotification

时间:2014-03-13 11:05:32

标签: scala akka scalatest

我有一些测试,大部分时间都会记录[akka://TopLevelSpec/system/IO-TCP/selectors/$a/0] received dead system message: DeathWatchNotification(Actor[akka://TopLevelSpec/user/IO-HTTP/listener-0#413174611],true,false)警告消息。我可以使用EventFilter捕获它,但问题是似乎存在竞争条件,并且有些时候消息发送,然后测试失败并且期望。 (简化版)我的代码和测试如下。有关避免此问题的任何提示吗?

下面是一个演示该问题的完整示例(您可能需要运行几次):

package com.netaporter.salad.lad
import akka.actor._
import akka.testkit.{ EventFilter, TestActorRef, ImplicitSender, TestKit }
import org.scalatest._
import spray.can.Http
import akka.actor.SupervisorStrategy.{ Restart, Stop }
import akka.actor.Terminated
import akka.actor.OneForOneStrategy

trait FooConfig {
  def createBarActor: ActorRef
  def createQuuxActor: ActorRef
}

trait Foo extends Actor {
  this: FooConfig =>

  val bar = createBarActor
  context watch bar

  val quux = createQuuxActor
  context watch quux

  override def supervisorStrategy: SupervisorStrategy = OneForOneStrategy() {
    case _ if context.child(sender.path.name).isDefined => Stop
  }

  def receive = {
    case Http.CommandFailed(_) => context stop self
    case Terminated(`bar`) | Terminated(`quux`) =>
      context stop self
  }
}

class ReallyDeadDuck extends Actor {
  def receive = {
    case Symbol(name) => throw new Exception(name)
  }
}

class FooSpec extends TestKit(ActorSystem("FooSpec")) with WordSpecLike with BeforeAndAfter with OneInstancePerTest with ShouldMatchers with ImplicitSender {

  after {
    system.shutdown()
  }

  trait Case {
    val top = TestActorRef(new Foo with FooConfig {
      def createBarActor = context.actorOf(Props[ReallyDeadDuck])
      def createQuuxActor = context.actorOf(Props[ReallyDeadDuck])
      def interface: String = "localhost"
      def port: Int = (10000 + math.random * 50000).toInt
    })
    watch(top)
  }

  "Foo" should {

    "stop itself if bar dies" in new Case {
      EventFilter.warning(pattern = "received dead system message", occurrences = 1) intercept {
        EventFilter[Exception](message = "bar", occurrences = 1) intercept {
          top.underlyingActor.bar ! 'bar
        }
      }
      expectTerminated(top)
    }

    "stop itself if quux dies" in new Case {
      EventFilter.warning(pattern = "received dead system message", occurrences = 1) intercept {
        EventFilter[Exception](message = "quux", occurrences = 1) intercept {
          top.underlyingActor.quux ! 'quux
        }
      }
      expectTerminated(top)
    }

  }

}

1 个答案:

答案 0 :(得分:2)

您可以将该特定消息静音,而不是声明它将会到达:

import akka.testkit.TestEvent.Mute
system.eventStream.publish(Mute(
  EventFilter.warning(pattern = "received dead system message")))