Search code examples
scalaplayframeworkguice

How to override a TypeLiteral in Scala Guice when testing


In my Module.scala I'm binding a concrete implementation of a trait defined as follows:

trait AccessGroupRepository[F[_]] {}

@Singleton
class AccessGroupRepositoryImpl @Inject()(db: OldDataBase, c: IOContextShift)
    extends AccessGroupRepository[IO] {}

and the binding is done using TypeLiteral:

bind(new TypeLiteral[AccessGroupRepository[IO]] {}).to(classOf[AccessGroupRepositoryImpl])

Now, I need to override this binding when testing with a Mockito mock:

override val application: Application = guiceApplicationBuilder
    .overrides(bind(new TypeLiteral[AccessGroupRepository[IO]] {}).to(agRepoMock))

but I get the following error:

overloaded method value bind with alternatives:
[error]   [T](implicit evidence$1: scala.reflect.ClassTag[T])play.api.inject.BindingKey[T] <and>
[error]   [T](clazz: Class[T])play.api.inject.BindingKey[T]
[error]  cannot be applied to (com.google.inject.TypeLiteral[api.v1.accessgroup.AccessGroupRepository[cats.effect.IO]])
[error]     .overrides(bind(repoTypeLiteral).to(agRepoMock))
[error]                ^

How could I solve that?

This question relates to How to bind a class that extends a Trait with a monadic type parameter using Scala Guice?


Solution

  • TypeLiteral isn't available yet in scala implementation of Play Guice API.

    Current valid solution for generics, is creating a test module with desired mock definitions, and passing it within overrides:

    object CustomMockComponentModule extends AbstractModule {
      val agRepoMock = ...
    
      @Provides
      @Singleton
      def mockBean(): AccessGroupRepository[IO] = agRepoMock
    }
    
    ...
    
    override val application: Application = guiceApplicationBuilder
        .overrides(CustomMockComponentModule)
        .build()