Scala 如何在集成测试中执行此控制器操作代码?

Scala 如何在集成测试中执行此控制器操作代码?,scala,playframework,integration-testing,Scala,Playframework,Integration Testing,我正在使用Scala Play框架编写一个集成测试 在控制器中,我有一个如下所示的函数: def myEndpoint: AnyAction = myActionProvider.securedEndpoint("myEndpoint") { implicit request => // Business logic Ok("") } myActionProvider.securedEndpoint使用和()将一些动作生成器链接在一起,并返回一个ActionBuilder

我正在使用Scala Play框架编写一个集成测试

在控制器中,我有一个如下所示的函数:

def myEndpoint: AnyAction = myActionProvider.securedEndpoint("myEndpoint") { implicit request =>
    // Business logic
    Ok("")
}
myActionProvider.securedEndpoint
使用
和()将一些动作生成器链接在一起,并返回一个
ActionBuilder

在我的集成测试中,我有以下几点:

val fakeRequest: FakeRequest = buildFakeRequest()
myController.myEndpoint.apply(fakeRequest)
假请求包含生成的安全令牌和我们的应用程序所需的其他头

我能够在
myActionProvider.securedEndpoint中中断并跟踪执行。但是,我无法在任何
invokeBlock
方法内部中断,也无法在控制器的业务逻辑内部中断。日志显示这些路径从未执行过

如果我将myController.myEndpoint.apply(fakeRequest)
的结果保存到变量,则其类型为
累加器[ByteString,result]
。看起来它包含了链式动作构建器和业务逻辑代码块,但Play从未执行它

代码不会抛出任何异常,也不会向控制台输出任何内容

我想知道这是否是我的测试语法错误。我还尝试了以下方法,但没有成功:

  • myController.myEndpoint{fakeRequest}
  • myController.myEndpoint()(fakeRequest)

是的,代码在“常规”环境下工作,例如非测试环境:)

我创建了一个关于如何测试控制器的工作示例。它基于Play 2.6.15和Guice,并使用
scalatestplus Play

libraryDependencies ++= Seq(
  "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2" % "test"
)
这是一个具有两个操作的控制器:

import javax.inject.Inject
import play.api.mvc._

class ApplicationController @Inject()(controllerComponents: ControllerComponents)
  extends AbstractController(controllerComponents) {

  def foo(): Action[AnyContent] = Action { request =>
    Ok(s"I am listening at ${request.uri}")
  }

  def bar: Action[String] = Action(parse.tolerantText) { request =>
    Ok(s"Received body of size: ${request.body.length}")
  }
}
带有显式主体解析器的操作确实返回一个
累加器
对象。有趣的是,带有默认主体解析器的操作返回一个
未来的

不过,在这两种情况下,
播放测试
库都提供了从两种结果类型中提取结果正文、状态和其他信息的帮助

import akka.stream.Materializer
import akka.util.ByteString
import org.scalatestplus.play._
import play.api.http.Status
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.streams.Accumulator
import play.api.mvc._
import play.api.test.Helpers._
import play.api.test._

import scala.concurrent.Future

class ApplicationControllerTest extends PlaySpec {

  "ApplicationController" should {

    val application = new GuiceApplicationBuilder().build()
    val controller = application.injector.instanceOf[ApplicationController]

    "return correct response for foo" in {
      val result: Future[Result] = controller.foo().apply(FakeRequest("GET", "/testUriFoo"))
      contentAsString(result) mustBe "I am listening at /testUriFoo"
      status(result) mustBe Status.OK
    }

    "return correct response for bar" in {
      implicit val mat: Materializer = application.materializer
      val fakeRequest = FakeRequest("POST", "/testUriBar").withTextBody("123456789")
      val result: Accumulator[ByteString, Result] = controller.bar().apply(fakeRequest)
      contentAsString(result) mustBe "Received body of size: 9"
      status(result) mustBe Status.OK
    }

  }

}
使用的资源:


谢谢。从您提供的资源中,我还了解到调用
controller.bar()(fakeRequest)
将返回一个
Future[Result]
,无需使用物化器。