【问题标题】:Dependency Injection in Tests in Play Scala App sPlay Scala 应用程序中的测试中的依赖注入
【发布时间】:2014-10-29 06:51:15
【问题描述】:

我有两个用于创建 Guice 测试模块的模拟对象。 我有两个问题:

  1. 如果我还要验证模拟交互,是否需要在每次测试之前创建模拟对象?我认为是的,为了实现它,我认为我需要使用“之前”块。

  2. 如何按照 DRY 原则为每个测试创建一个 guice 测试模块 :)(即如何为每个测试使用相同的代码块)

这是我目前的代码

    class SampleServiceTest extends Specification with Mockito with BeforeExample {

      //Mock clients
      var mockSample: SampleClient = null   //this ugly but what is the right way?
      var mockRedis: RedisClient = null

      def before = {
        println("BEFORE EXECUTED")
        mockSample = mock[SampleClient]
        mockRedis = mock[RedisClient]
      }

      def after = {
        //there were noMoreCallsTo(mockRedis)
        //there were noMoreCallsTo(mockSample)
      }

      object GuiceTestModule extends AbstractModule {   //Where should I create this module
        override def configure = {
          println(" IN GUICE TEST")
          bind(classOf[Cache]).toInstance(mockRedis)
          bind(classOf[SampleTrait]).toInstance(mockSample)
        }
      } 

      "Sample service" should {
        "fetch samples from redis should retrieve data" in {
         running(FakeApplication()) {
           println("TEST1")
           val injector = Guice.createInjector(GuiceTestModule)
           val client = injector.getInstance(classOf[SampleService])
           mockRedis.get("SAMPLES").returns(Some(SampleData.redisData.toString))
           val result = client.fetchSamples
           there was one(mockRedis).get("SAMPLES")   //verify interactions
           Json.toJson(result) must beEqualTo(SampleData.redisData)
         }
       }
     }
   }

【问题讨论】:

    标签: scala playframework mockito guice specs2


    【解决方案1】:
    1. 是的
    2. 您可以使用org.specs2.specification.Scope

    像这样:

    trait TestSetup extends Scope {
      val mockSample = mock[SampleClient]
      val mockRedis = mock[RedisClient]
    
      object GuiceTestModule extends AbstractModule {
        override def configure = {
          println(" IN GUICE TEST")
          bind(classOf[Cache]).toInstance(mockRedis)
          bind(classOf[SampleTrait]).toInstance(mockSample)
        }
      } 
    }
    

    然后在每个测试用例中使用它

    "something with the somtehing" in new TestSetup {
       // you can use the mocks here with no chance that they
       // leak inbetween tests
     }
    

    我猜你也已经将注入器放入你的游戏应用程序中,以便控制器等实际使用你的模拟对象,没有在游戏中使用 Guice,所以我不知道该怎么做。

    【讨论】:

    • 您的建议绝对有道理。但是,当我这样做时,我的交互验证将停止工作。例如there was no(mockRedis).get("SAMPLES") 也通过了,但它应该失败?你知道为什么
    • 我想你需要告诉你的应用程序使用你的模拟 Guice 模块,但我不知道该怎么做。也许这会有所帮助(尤其是他们如何在 dev 和 prod 中使用不同的模块):eng.kifi.com/play-framework-dependency-injection-guice
    • 好吧,我使用isolated 参数让它工作了。回答您的问题:在我的情况下,我不需要告诉我的应用程序使用 Guice,因为我没有启动应用程序只是运行单元测试。我使用val injector = Guice.createInjector(GuiceTestModule) 创建了注入器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    相关资源
    最近更新 更多