Как протестировать Play REST API с помощью Json BodyParser?

Я хотел бы написать простой тест для контроллера, который принимает тело json. Но как только я добавляю parse.json BodyParser в действие, мои тесты больше не могут быть скомпилированы. Программа установки представляет собой обычный проект play-scala-seed.

Ошибка:

[error] ... could not find implicit value for parameter mat: akka.stream.Materializer
[error]       status(home) mustBe OK
[error]             ^

HomeController:

def index() = Action { implicit request =>
  Ok
}

def json() = Action(parse.json) { implicit request =>
  Ok
}

HomeControllerSpec:

class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {
  "HomeController POST" should {
    "answer Ok" in {
      val controller = new HomeController(stubControllerComponents())
      val home = controller.json().apply(FakeRequest(POST, "/"))
      status(home) mustBe OK
    }
  }

person Saskia    schedule 21.03.2018    source источник


Ответы (2)


Кажется, есть две проблемы с рассматриваемым кодом, касающимся вызовов stubControllerComponents и FakeRequest.

Helpers.stubControllerComponents по умолчанию создает ControllerComponents с NoMaterializer который просто выдает исключение при использовании, поэтому нам нужно предоставить фактический материализатор следующим образом:

       implicit val materializer = ActorMaterializer()(ActorSystem())

       Helpers.stubControllerComponents(
         playBodyParsers = Helpers.stubPlayBodyParsers(materializer)
       ) 

Вторая проблема связана с FakeRequest, где нам нужно предоставить тело следующим образом (иначе мы получим ошибку 4xx):

FakeRequest(POST, "/json").withBody(Json.obj("name" -> "Jon Doe"))

Принимая во внимание вышеизложенное, мы можем написать полный тест следующим образом:

class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest {
  "HomeController POST" should {
    "answer Ok" in {
       implicit val materializer = ActorMaterializer()(ActorSystem())

       val controllerComponents = 
         Helpers.stubControllerComponents(
           playBodyParsers = Helpers.stubPlayBodyParsers(materializer)
         ) 

       val controller = new HomeController(controllerComponents)

       val fakeRequest = 
         FakeRequest(POST, "/json").withBody(Json.obj("name" -> "Jon Doe"))

       val home = call(controller.json(), fakeRequest)

       status(home) mustBe OK
    }
  }
}
person Mario Galic    schedule 30.04.2018

Кажется, вам нужно внедрить материализатор в ваш контроллер:

class Controller @Inject() (implicit val mat: Materializer) { ??? }

person Learner    schedule 21.03.2018
comment
Он отлично работает, когда я запускаю приложение, но не в тестах. Я нашел stackoverflow.com/questions/36888253/ и добавил неявные значения для ActorSystem и материализатора в моем тестовом классе. Он компилируется, но всегда возвращает 400 без вызова моего метода. - person Saskia; 22.03.2018