Отключить синглтон при тестировании с ScalaTest в Play для Scala
У меня есть следующее @Singleton
в моем приложении Play for Scala, которое загружается при запуске:
@Singleton
class Scheduler @Inject()(@Named("mainEtl") mainEtl: ActorRef, system: ActorSystem) {
// some code
}
Это модуль, в котором объявлен планировщик. Модуль включен в application.conf
:
class Module extends AbstractModule {
def configure() = {
bind(classOf[Scheduler]).asEagerSingleton
}
}
И определение соответствующего модуля для настройки @Named
введенный объект, также объявленный в application.conf
:
class AkkaBindings extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[MainEtl]("mainEtl")
}
}
Когда я запускаю любой тест ScalaTest, по-видимому, запускается синглтон, потому что я получаю сообщение об ошибке, что он не находит MainEtl
(объект вводится в Scheduler
учебный класс). Дело в том, что мне не нужно запускать синглтон для моих тестов, поэтому мне нужно отключить его.
Вот как я вызываю приложение Play в своих тестах:
class ManageBanksTest extends PlaySpec with OneAppPerSuite with MockitoSugar {
implicit override lazy val app = new GuiceApplicationBuilder().build
// more test code
}
Вот как я пытался отключить его, но он не работает, так как я получаю ту же ошибку:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Scheduler]
.build
В качестве альтернативы, я мог бы издеваться Scheduler
, но я должен был бы высмеять также @Named
Впрыскиваемый объект, и я не мог найти информацию о том, как этого добиться.
Есть идеи?
2 ответа
Это решение: отключить класс Module, чтобы не объявлять планировщик как singleton:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Module]
.build
import com.google.inject.AbstractModule
import com.google.inject.name.Names
import org.specs2.mock.Mockito
import play.api.inject.guice.{GuiceApplicationBuilder, GuiceableModule}
val modules = Option(new AbstractModule {
override def configure() = {
val mockMainETL = mock[MainEtl]
bind(classOf[ActorRef])
.annotatedWith(Names.named("mainEtl"))
.toInstance(mockMainETL)
val mock1 = mock[ManageBanksDAO]
mock1.readMany answers { _ => Future{seqMany}}
val mockManageBanks = mock[ManageBanks]
bind(classOf[ManageBanks]).toInstance(new ManageBanks(mock1))
}
})
lazy val app = new GuiceApplicationBuilder()
.overrides(modules.map(GuiceableModule.guiceable).toSeq: _*)
.build
Попробуйте настроить макет внутри модулей и добавить эти модули во время инициализации приложения. Это будет вводить пользовательские макеты.
Также вместо этого:
val controller = new ManageBanks(mock1)
Попробуй это:
val controller = app.injector.instanceOf(classOf[ManageBanks])