Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Akka testing - sender is deadLetters

I've got the following test spec:

class SiteCheckerSpec extends TestKit(ActorSystem("testSystem"))
                     with ImplicitSender
                     with BeforeAndAfterAll
                     with Matchers
                     with WordSpecLike {

val sites = List(
   "www.google.com",
   "www.apple.com",
   "www.gazeta.pl"
)

"Tested SiteChecker actor" must {
  "not receive message" in {
      val testedActor = system.actorOf(Props(new SiteChecker(sites.size) with TestActorContextCreationSupport {
          override def actorRefFactory = system
      }))

      testedActor ! SiteChecker.CheckSitesTitles(sites)
      expectNoMsg()
  }
}

override protected def afterAll(): Unit = TestKit.shutdownActorSystem(system)
}

And following actor:

class SiteChecker(workersCount: Int) extends Actor
                                    with ActorLogging
                                    with ActorContextCreationSupport {

val resultMap = mutable.HashMap.empty[String, String]
var originalSender: Option[ActorRef] = None

val workers = (
  for (i <- 1 to workersCount) yield createChildren(SiteCheckerWorker.props())
).toList

def actorRefFactory: ActorRefFactory = context

override def receive: Actor.Receive = {

case SiteChecker.CheckSitesTitles(sites) =>
  log.info(s"Sites to check $sites")
  println(sender)
  originalSender = Some(sender)
  workers.zip(sites).foreach(
    t => t._1 ! SiteCheckerWorker.CheckSiteTitle(t._2)
  )

case SiteCheckerWorker.SiteTitle(site, title) =>
  log.info(s"Obtained title $title for site $site")
  resultMap += (site -> title)
  if (resultMap.size == workers.size) {
    originalSender.get ! SiteChecker.SitesTitles(resultMap.toMap)
    context.children.foreach(context.stop)
  }
}
}

Test case is always passing because orginalSender in actor class is deadLetters, not reference to test sender.

Here is the log output after test is run:

 Actor[akka://testSystem/deadLetters]
 [INFO] [02/13/2014 18:53:59.150] [testSystem-akka.actor.default-dispatcher-2]    [akka://testSystem/user/$a] Sites to check List(www.google.com, www.apple.com, www.gazeta.pl)
 [INFO] [02/13/2014 18:53:59.154] [testSystem-akka.actor.default-dispatcher-3] [akka://testSystem/user/$a] Obtained title www.gazeta.pl for site www.gazeta.pl
 [INFO] [02/13/2014 18:53:59.157] [testSystem-akka.actor.default-dispatcher-3] [akka://testSystem/user/$a] Obtained title www.google.com for site www.google.com
 [INFO] [02/13/2014 18:53:59.158] [testSystem-akka.actor.default-dispatcher-5] [akka://testSystem/user/$a] Obtained title www.apple.com for site www.apple.com
 [INFO] [02/13/2014 18:53:59.163] [testSystem-akka.actor.default-dispatcher-4] [akka://testSystem/deadLetters] Message [actor.site.SiteChecker$SitesTitles] from  Actor[akka://testSystem/user/$a#735871082] to Actor[akka://testSystem/deadLetters] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

Why is this happening?

like image 216
Tomek Zaremba Avatar asked Nov 30 '22 19:11

Tomek Zaremba


2 Answers

In my case this happened because my test class extended TestKit, but did not mix in ImplicitSender.

like image 146
Zoltán Avatar answered Dec 05 '22 04:12

Zoltán


The only possibility that I can see is that you have another implicit ActorRef in scope in your test procedure, leading to an ambiguous implicit argument which then means that none of them is picked up.

like image 26
Roland Kuhn Avatar answered Dec 05 '22 06:12

Roland Kuhn