fail to simulate play api Request

58 views Asked by At

I have a class that have that receives Option[Request[_]] as an implicit (play.api.mvc.Request):

class MyClass @Inject()(...)(implicit val request: Option[Request[_]]) { ...

my problem is in my test im using play.api.test.inject like:

  val myClass: MyClass = inject[MyClass]

and to be able to do that in my test i have to bring this Request implicit. so the way i did was with mockito.ArgumentMatchers like this:

  implicit val origReq: Option[Request[_]] = any[Option[Request[_]]]

but when i run the test i get this error:

An exception or error caused a run to abort: Guice configuration errors:

1) No implementation for scala.Option<play.api.mvc.Request<?>> was bound.
  while locating scala.Option<play.api.mvc.Request<?>>
    for the 3rd parameter of streams.MyClass.<init>(MyClass.scala:16)
  while locating streams.MyClass

1 error 
com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for scala.Option<play.api.mvc.Request<?>> was bound.
  while locating scala.Option<play.api.mvc.Request<?>>
    for the 3rd parameter of streams.MyClass.<init>(MyClass.scala:16)
  while locating streams.MyClass

what am i doing wrong? :/

1

There are 1 answers

0
AlexITC On

The problem is that you are defining a class that's supposed to be instantiated by guice which requires an optional request, it is very likely that you need this request to be actually request-scoped (a different object in on each request) which isn't straightforward in play.

I don't know how inject[MyClass] behaves, I guess that it won't look for the implicit optional request on the scope but it will try to instantiate MyClass using the available modules (Just In Time bindings aren't enough because Request[_] is not concrete, you could get the tests passing by defining a specific binding for your test but it won't be that easy to get the app working), in any case, providing objects with generic types is not that simple, because there are many possible implementations for a single Request[_], think about replacing _ by Int, String, etc.

A good idea would be to refactor MyClass to require the implicit request on each method instead, which resolves the problematic provisioning.

If you still want to go with the implicit request on the constructor, you'll need to look into request-scoped bindings on play, which is a topic by itself.