scala 发送 FakeRequest 时如何为 akka.stream.Materializer 提供隐式值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36945414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 08:14:33  来源:igfitidea点击:

How do I supply an implicit value for an akka.stream.Materializer when sending a FakeRequest?

scalaplayframeworkplayframework-2.0akkaakka-stream

提问by gknauth

I'm trying to make sense of the error(s) I'm seeing below, and to learn how to fix it.

我试图理解我在下面看到的错误,并学习如何修复它。

could not find implicit value for parameter materializer: akka.Stream.Materializer
  val fut: Future[Result] = action.apply(fakeRequest).run
                                  ^
not enough arguments for method run (implicit materializer: akka.stream.Materializer)scala.concurrent.Future[play.api.mvc.Result].
Unspecified value parameter materializer.
  val fut: Future[Result] = action.apply(fakeRequest).run
                                  ^

Here is the test code that produced the error(s):

这是产生错误的测试代码:

package com.foo.test

import com.foo.{Api, BoundingBox}
import org.scalatest.{FlatSpec, Matchers}
import play.api.libs.json._
import play.api.mvc._
import play.api.test.{FakeHeaders, FakeRequest}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

class TestJmlPlay extends FlatSpec with Matchers {

  val bbox = new BoundingBox(-76.778154438007732F, 39.239828198015971F, -76.501003519894326F, 39.354663763993926F)

  "latitudes" should "be between swLat and neLat" in {
    val action: Action[AnyContent] = (new Api).getForPlay(bbox)
    val jsonStr = getStringFromAction(action)
    areLatitudesOk(jsonStr, bbox) shouldBe true
  }

  private def getStringFromAction(action:Action[AnyContent]):String = {
    val fakeRequest: Request[String] = new FakeRequest("fakeMethod", "fakeUrl", new FakeHeaders, "fakeBody")
    val fut: Future[Result] = action.apply(fakeRequest).run  // <== ERROR!
    val result = Await.result(fut, 5000 milliseconds)
    result.body.toString
  }

  private def areLatitudesOk(jsonStr: String, bbox: BoundingBox): Boolean = ...

}

回答by Ramón J Romero y Vigil

You can create an implicit ActorMaterializerwithin your test class which will use testkit's ActorSystem:

您可以ActorMaterializer在将使用 testkit 的测试类中创建一个隐式ActorSystem

import akka.testkit.TestKit
import akka.actor.ActorSystem

class TestJmlPlay(_system : ActorSystem) extends TestKit(_system) ... {

  implicit val materializer: ActorMaterializer = ActorMaterializer()

  val bbox = ...

回答by Bartosz Pioruński

You don't need Materializer.

你不需要物化器。

I believe you are calling not the right action.applymethod.
You want def apply(request: Request[A]): Future[Result]
To call the right, you need FakeRequest[AnyContent], same parametrized type as action:Action[AnyContent].This type is forced by PlayBodyParser I believe you set for your action.

我相信你调用的action.apply方法不正确。
你想要def apply(request: Request[A]): Future[Result]
调用正确的,你需要FakeRequest[AnyContent],与 相同的参数化类型action:Action[AnyContent]。这种类型是由 PlayBodyParser 强制的,我相信你为你的动作设置的。

After that you don't need .runcall

之后你不需要.run打电话