在 Play for Scala 中使用 ScalaTest 进行测试时禁用单例
Disable singleton when testing with ScalaTest in Play for Scala
我的 Play for Scala 应用程序中有以下 @Singleton
在启动时加载:
@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 测试时,显然单例启动 运行ning 因为我收到一条错误消息说它找不到 MainEtl
(对象注入 Scheduler
class)。重点是我不需要测试单例运行,所以我需要禁用它。
这是我在测试中调用 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
注入的对象,但我找不到有关如何实现该目标的信息。
有什么想法吗?
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])
这是解决方案:禁用模块 class 不要将调度程序声明为单例:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Module]
.build
我的 Play for Scala 应用程序中有以下 @Singleton
在启动时加载:
@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 测试时,显然单例启动 运行ning 因为我收到一条错误消息说它找不到 MainEtl
(对象注入 Scheduler
class)。重点是我不需要测试单例运行,所以我需要禁用它。
这是我在测试中调用 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
注入的对象,但我找不到有关如何实现该目标的信息。
有什么想法吗?
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])
这是解决方案:禁用模块 class 不要将调度程序声明为单例:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Module]
.build