Question

I have a few tests that most of the time log a [akka://TopLevelSpec/system/IO-TCP/selectors/$a/0] received dead system message: DeathWatchNotification(Actor[akka://TopLevelSpec/user/IO-HTTP/listener-0#413174611],true,false) warning message. I can capture it using an EventFilter, but the problem is that there seems to be a race condition and some of the time the message is not sent and the test then fails with the expectation. (A simplified version of) my code and test is below. Any tips for avoiding this issue?

Below is a complete example that demonstrates the issue (you might have to run it a few times):

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)
    }

  }

}
Was it helpful?

Solution

You can just mute that specific message instead of asserting that it will arrive:

import akka.testkit.TestEvent.Mute
system.eventStream.publish(Mute(
  EventFilter.warning(pattern = "received dead system message")))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top