Как я могу выполнить этот код действия контроллера в интеграционном тесте? - PullRequest
0 голосов
/ 09 ноября 2018

Я пишу интеграционный тест, используя платформу Scala Play.

У меня в контроллере есть функция, которая выглядит следующим образом:

def myEndpoint: AnyAction = myActionProvider.securedEndpoint("myEndpoint") { implicit request =>
    // Business logic
    Ok("")
}

myActionProvider.securedEndpoint объединяет некоторые компоновщики действий, используя andThen(), и возвращает ActionBuilder.

В моем интеграционном тесте у меня есть следующее:

val fakeRequest: FakeRequest = buildFakeRequest()
myController.myEndpoint.apply(fakeRequest)

Ложный запрос содержит сгенерированный токен безопасности и другие заголовки, необходимые для нашего приложения.

Я могу прорваться внутрь myActionProvider.securedEndpoint и следить за исполнением. Однако я не могу взломать ни один из методов invokeBlock, ни внутреннюю бизнес-логику контроллера. Ведение журнала показывает, что эти пути никогда не выполняются.

Если я сохраню результат myController.myEndpoint.apply(fakeRequest) в переменной, его тип будет Accumulator[ByteString, Result]. Похоже, что он содержит цепочки построителей действий и блок кода бизнес-логики, но Play никогда не выполнит его.

Код не генерирует исключений и ничего не выводится на консоль.

Мне было интересно, была ли это ошибка в моем тестовом синтаксисе. Я также попробовал следующее, но безрезультатно:

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

И да, код работает в «обычном» режиме, например не тестирующая среда:)

1 Ответ

0 голосов
/ 09 ноября 2018

Я создал рабочий пример о том, как проверить контроллер здесь . Он основан на 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}")
  }
}

Действия с явными синтаксическими анализаторами тела действительно возвращают объект Accumulator. Интересно, что действия с парсером тела по умолчанию возвращают Future.

В обоих случаях, однако, библиотека play-test предоставляет помощников для извлечения тела результата, статуса и других данных из обоих типов результатов.

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
    }

  }

}

Использованные ресурсы:

...