scalaplayframework-2.6

how can i found out from where an implicit value is being picked


I am observing a strange behavior. In on of my test cases, I am using contentAsJson. In that test case, the compiler is not complaining that I have to provide an implicit value for Timeout and Materializer

class UserControllerUnitSpec extends PlaySpec with BeforeAndAfterAll with BeforeAndAfterEach with OneAppPerSuiteWithComponents{
..
  "User signup request with body but with incorrect profile data " should {
    "return error message " in {

...val resultFuture: Future[Result] = testEnv.controller.signupUser(request)
    val responseBodyAsJsValue: JsValue = contentAsJson(resultFuture)//works
...
}
}

But in another test case, the compiler gives error that I need to provide the value

class QuestionsControllerUnitSpec extends PlaySpec with BeforeAndAfterAll with BeforeAndAfterEach with OneAppPerSuiteWithComponents{
...
"newQuestion" should {
    "should return error if the size of the body in the request is more than the maximum allowed size" in {
...
val response:Accumulator[ByteString,Result] = questionController.newQuestion(request)
val responseBody = contentAsJson(response)//(Timeout(Duration(5000,"millis")),testEnv.testEnv.mat). 
...
}

I get error

Error:(1485, 39) could not find implicit value for parameter mat: akka.stream.Materializer
      val responseBody = contentAsJson(response)//(Timeout(Duration(5000,"millis")),testEnv.testEnv.mat)

How can I debug why one is working but the other isn't?

UPDATE - added return types after Mario's answer.


Solution

  • Try providing implicit Materializer like so

    import play.api.test.Helpers._
    implicit val actorSystem = ActorSystem("test")
    implicit val materializer = ActorMaterializer()
    val responseBody = contentAsJson(response)
    

    instead of explicit testEnv.testEnv.mat

    contentAsJson(response)(Timeout(Duration(5000,"millis")),testEnv.testEnv.mat)
    

    Regarding the difference between the two tests, note there are two overloaded versions of contentAsJson

    def contentAsJson(of: Future[Result])(implicit timeout: Timeout, mat: Materializer = NoMaterializer): JsValue
    
    def contentAsJson(of: Accumulator[ByteString, Result])(implicit timeout: Timeout, mat: Materializer): JsValue
    

    where in the first case we see default Materializer argument is provided

    mat: Materializer = NoMaterializer
    

    while in the second case we have to provided our own. Therefore it is likely that in the first test the type of resultFuture is Future[Result] whilst in the second test the return type of response is Accumulator.

    Regarding finding out where the implicit is provided from, personally I use IntelliJ's View | Show Implicit Hints feature.