【问题标题】:how can i found out from where an implicit value is being picked我怎样才能找到从哪里选择隐式值
【发布时间】:2019-08-20 15:58:16
【问题描述】:

我观察到一种奇怪的行为。在我的一个测试用例中,我使用的是contentAsJson。在那个测试用例中,编译器并没有抱怨我必须为TimeoutMaterializer 提供一个implicit

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

但在另一个测试用例中,编译器给出了我需要提供值的错误

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

我得到错误

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)

我如何调试为什么一个工作而另一个不工作?

更新 - 在马里奥的回答之后添加了返回类型。

【问题讨论】:

  • 至少有礼貌地告诉你为什么这个问题被标记了!

标签: scala playframework-2.6


【解决方案1】:

尝试像这样提供隐式Materializer

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

而不是明确的testEnv.testEnv.mat

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

关于两个测试的区别,注意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

在第一种情况下,我们看到提供了默认的Materializer 参数

mat: Materializer = NoMaterializer

而在第二种情况下,我们必须提供自己的。因此很可能在第一个测试中resultFuture 的类型是Future[Result],而在第二个测试中response 的返回类型是Accumulator

关于找出隐式是从哪里提供的,我个人使用 IntelliJ 的 View | Show Implicit Hints 功能。

【讨论】:

  • 你对返回类型很感兴趣。 signupUserAction 类型的 Action[AnyContent]newQuestionAction 类型 Action[Either[MaxSizeExceeded,AnyContent]。但是为什么调用一个返回Future[Result]而调用另一个返回Accumulator[ByteString,Result]
  • 另外,如果你看看我之前打开的这个问题,当NoMaterializer 使用默认值stackoverflow.com/questions/57577155/… 时,我不应该得到Getting .UnsupportedOperationException: NoMaterializer does not provide an ExecutionContext Error 错误吗?
  • Action[Either[MaxSizeExceeded,AnyContent] 向我表明您正在使用自定义解析器。你能用相关的控制器 sn-ps 编辑问题吗?
  • 保持主题分开,请查看stackoverflow.com/questions/57581602/…
  • 总之,我想限制传入请求的大小。该代码在开发环境中工作,但我正在努力为其创建单元测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多