Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
185 views
in Technique[技术] by (71.8m points)

scala - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...