Richeek
Richeek

Reputation: 2220

Dependency Injection in Tests in Play Scala App s

I have two mock objects which I use to create a Guice test module. I have two questions:

  1. Do I need to create mock objects before every test if I am verifying mock-interactions as well? I think yes, and to achieve it I think I need to use "before" block.

  2. How to create a guice test module for every test following DRY principle :) (i.e. how to use the same code-block for every test)

This is the code I have so-far

    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)
         }
       }
     }
   }

Upvotes: 2

Views: 3252

Answers (1)

johanandren
johanandren

Reputation: 11479

  1. Yes
  2. You can use a org.specs2.specification.Scope

Like this:

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)
    }
  } 
}

and then use that in each testcase

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

I guess you also have go the injector into your play application so that controllers etc. will actually use your mocked objects, haven't used Guice with play so I'm not sure how to do that.

Upvotes: 3

Related Questions