Gregra
Gregra

Reputation: 803

Scala Play Framework - getting "cannot enqueue after timer shutdown" error when running tests that involve Akka

When trying to unit test my code (with Mockito) that runs an Akka scheduler I keep getting "cannot enqueue after timer shutdown".

My code:

Global.scala

override def onStart(app: Application){
    Some(Akka.system.scheduler.schedule(23.hours, 24.hours) {
         println("I run all the time")
    })
}

TasksRepositorySpec.scala

def insertTestData() = {
    running(FakeApplication()) {
       //some code
    }
}

When I run:

activator test

I get:

[info] TasksRepositorySpec
[info] 
[error] ! 
[error]  cannot enqueue after timer shutdown (Scheduler.scala:270)
[error] akka.actor.LightArrayRevolverScheduler.schedule(Scheduler.scala:270)
[error] akka.actor.Scheduler$class.schedule(Scheduler.scala:79)
[error] akka.actor.LightArrayRevolverScheduler.schedule(Scheduler.scala:182)
[error] Global$.onStart(Global.scala:56)
[error] play.api.GlobalPlugin.onStart(GlobalSettings.scala:272)
[error] play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:91)
[error] play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:91)
[error] play.api.Plugins.foreach(Plugins.scala:57)
[error] play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:91)
[error] play.api.Play$$anonfun$start$1.apply(Play.scala:91)
[error] play.api.Play$$anonfun$start$1.apply(Play.scala:91)
[error] play.utils.Threads$.withContextClassLoader(Threads.scala:21)
[error] play.api.Play$.start(Play.scala:90)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:41)
[error] play.api.test.Helpers$.running(Helpers.scala:363)
[error] repositories.TasksRepositorySpec.insertData(TasksRepositorySpec.scala:69)
[error] repositories.TasksRepositorySpec$$anonfun$2.apply$mcI$sp(TasksRepositorySpec.scala:88)
[error] repositories.TasksRepositorySpec$$anonfun$2.apply(TasksRepositorySpec.scala:88)
[error] repositories.TasksRepositorySpec$$anonfun$2.apply(TasksRepositorySpec.scala:88)

I use play 2.4

Any help will be appreciated

Upvotes: 4

Views: 2591

Answers (1)

Choucri
Choucri

Reputation: 250

Sorry I didn't find a solution, but only a workaround. It consists in using a fake Global object for tests where onStart() and onStop() methods are empty.

First you need to split your Global object into a trait and an empty object:

Global.scala

object Global extends Global

trait Global extends GlobalSettings { ... }

Then in your test code, you can create a fake Global:

Fake.scala

object FakeGlobal extends Global {
  override def onStart(app: Application): Unit = {}
  override def onStop(app: Application): Unit = {}
}

object Fake {
  // This has to be a method, cannot be a value
  def application() = FakeApplication(withGlobal = Some(FakeGlobal))
}

And finally use it in your tests:

TasksRepositorySpec.scala

def insertTestData() = {
  running(Fake.application()) {
    //some code
  }
}

It works for me. Hope it helps!

Upvotes: 1

Related Questions