【问题标题】:Disable singleton when testing with ScalaTest in Play for Scala在 Play for Scala 中使用 ScalaTest 进行测试时禁用单例
【发布时间】:2017-09-17 02:39:55
【问题描述】:

我的 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 测试时,显然单例开始运行,因为我收到一条错误消息,指出它找不到 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 注入的对象,我找不到有关如何实现它的信息。

有什么想法吗?

【问题讨论】:

  • 能分享一下你写到现在的测试课吗?
  • 添加了测试类,注意@Singleton在测试中没有被调用,Play在后台运行。

标签: scala playframework playframework-2.0 scalatest


【解决方案1】:
   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])

【讨论】:

  • 我收到以下错误:recursive value mockMainETL needs typeconfigure() 方法中,所以我添加了类型:val mockMainETL: MainEtl = mock[MainEtl] 但我在.toInstance(mockMainETL) 中收到此错误:type mismatch; found : tasks.etl.MainEtl required: akka.actor.ActorRef Note: implicit value app is not applicable here because it comes after the application point and it lacks an explicit result type跨度>
  • val mockMainETL: ActorRef = mock[MainEtl] 试试这个。
  • 我收到此错误:type mismatch; found : tasks.etl.MainEtl required: akka.actor.ActorRef Note: implicit value app is not applicable here because it comes after the application point and it lacks an explicit result type
  • 从你的应用中移除隐式
  • 我仍然收到type mismatch; found : tasks.etl.MainEtl required: akka.actor.ActorRef `val mockMainETL: ActorRef = mock[MainEtl]`
【解决方案2】:

这是解决方案:禁用 Module 类而不将 Scheduler 声明为单例:

implicit override lazy val app = new GuiceApplicationBuilder()
    .disable[Module]
    .build

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 2016-01-18
    相关资源
    最近更新 更多