NullPointerException при тестировании контроллера в Play 2.6

Я работаю над приложением Scala Play 2.6, которое использует ReactiveMongo. Я следовал примеру HomeControllerSpec.scala установки Play 2.6 по умолчанию (play-scala-seed.g8), чтобы протестировать мой ProjectController, создав его новый экземпляр, но я получаю файл NullPointerException.

Вот мой контроллер:

class ProjectController @Inject()(
      cc: ControllerComponents,
      val reactiveMongoApi: ReactiveMongoApi
  )(implicit ec: ExecutionContext) extends AbstractController(cc) with I18nSupport {

  def collection: Future[JSONCollection] = reactiveMongoApi.database.map(
    _.collection[JSONCollection]("project")
  )

  def listProjects: Action[AnyContent] = Action.async { implicit request =>
    val futureProjectsList: Future[List[Project]] = collection.flatMap(
      _.find(Json.obj())
      .projection(Json.obj())
      .cursor[Project]()
      .collect[List](-1, Cursor.FailOnError[List[Project]]())
    )

    for {
      projectsList <- futureProjectsList
    } yield {
      Ok(views.html.project.list(projectsList))
    }
  }
}

А это мой тест:

class ProjectControllerSpec extends PlaySpec
  with GuiceOneAppPerTest
  with Injecting
  with MockitoSugar {

  val mockedReactiveMongoApi: ReactiveMongoApi = mock[ReactiveMongoApi]
  val mockedExecutionContext: ExecutionContext = mock[ExecutionContext]

  "ProjectController GET" should {
    "render the 'List of Projects' page from a new instance of controller" in {
      val controller: ProjectController = new ProjectController(
                                                      stubControllerComponents(),
                                                      mockedReactiveMongoApi
                                                    )(mockedExecutionContext) {
        override def collection: Future[JSONCollection] = mock[Future[JSONCollection]]
      }
      val result = controller.listProjects().apply(FakeRequest(GET, "/projects"))

      status(result) mustBe OK
      contentType(result) mustBe Some("text/html")
      contentAsString(result) must include ("Projects")
    }
  }
}

Но когда я запускаю тест, я получаю:

[info]   java.lang.NullPointerException:
[info]   at controllers.ProjectController.$anonfun$listOfProjects$1(ProjectController.scala:51)
[info]   at play.api.mvc.ActionBuilderImpl.invokeBlock(Action.scala:482)
[info]   at play.api.mvc.ActionBuilderImpl.invokeBlock(Action.scala:480)
[info]   at play.api.mvc.ActionBuilder$$anon$2.apply(Action.scala:419)
[info]   at controllers.ProjectControllerSpec.$anonfun$new$2(ProjectControllerSpec.scala:40)
[info]   at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:20)

Я также запускаю 2 других теста для этих контроллеров, и они проходят (рендеринг страницы из приложения путем внедрения контроллера, рендеринг с маршрутизатора). Итак, как я могу пройти этот тест? Спасибо заранее за вашу помощь.


person consuela    schedule 22.05.2018    source источник


Ответы (1)


NullPointerException возникает из-за использования фиктивных объектов, у которых нет определенного поведения. Поэтому, когда выполнение достигает reactiveMongoApi.database, это вызовет исключение.

Этот проект github представил способ имитации реактивного mongo api, но на самом деле он больше не поддерживается. .

Вы также можете проверить acolyte, который позволяет имитировать соединение монго.

Кстати, вы не должны использовать моки для ExecutionContext, иначе ваши Future не будут работать

person vdebergue    schedule 22.05.2018