1

NullPointerException在测试处理表单的操作时遇到。有两种操作,一种用于显示,一种用于处理表单。测试第一个很好;但是,测试第二个会引发异常。这只发生在单元测试中;该应用程序工作正常(即,通过浏览器)。我不知道会发生什么。谁能帮我解释一下?我正在测试的代码如下。

  • 斯卡拉:2.11.8
  • SBT:0.13.11
  • 播放框架:2.5.2

构建.sbt

lazy val root = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
  "org.mockito" % "mockito-core" % "1.10.19" % Test,
  "org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test
)

项目/plugins.sbt

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.2")

配置/路由

GET     /           controllers.FormController.showForm
POST    /           controllers.FormController.processForm

应用程序/控制器/FormController.scala

package controllers

import javax.inject.Inject

import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc._

case class UserData(name: String, email: String)

class FormController @Inject()(val messagesApi: MessagesApi) extends
  Controller with
  I18nSupport {

  def showForm = Action {
    Ok(views.html.showForm(getForm))
  }

  def processForm = Action { implicit request =>
    getForm.bindFromRequest.fold(
      errForm => Ok(views.html.showForm(errForm)),
      userData => Ok(userData.toString)
    )
  }

  val getForm: Form[UserData] = Form(mapping(
    "name" -> nonEmptyText,
    "email" -> email
  )(UserData.apply)(UserData.unapply))
}

意见/main.scala.html

@(content: Html)

<!DOCTYPE html>
<html lang="en">
<body>
  @content
</body>
</html>

意见/showForm.scala.html

@import helper._

@(myForm: Form[UserData])(implicit messages: Messages)

@main {
  <h3>Form</h3>
  @form(action = routes.FormController.processForm()) {
    @inputText(myForm("name"))
    @inputText(myForm("email"))
    <input type="submit" value="Submit">
  }
}

测试/控制器/FormControllerSpec.scala

package controllers

import org.scalatest.mock.MockitoSugar
import org.scalatestplus.play.PlaySpec
import play.api.i18n.MessagesApi
import play.api.test.Helpers._
import play.api.test._

class FormControllerSpec extends PlaySpec with MockitoSugar {
  "FormController" when {
    "showForm" should {
      "display the form" in {
        val cut = new FormController(mock[MessagesApi])
        val response = cut.showForm(FakeRequest())
        status(response) mustBe OK
      }
    }

    "processForm" should {
      "redisplay the form in case of form errors" in {
        val cut = new FormController(mock[MessagesApi])
        val req = FakeRequest(POST, routes.FormController.processForm.path)
        val response = cut.processForm(req)
        status(response) mustBe OK
      }
    }
  }
}

运行测试的输出:

[info] FormControllerSpec:
[info] FormController
[info]   when showForm
[info]   - should display the form
[info]   when processForm
[info]   - should redisplay the form in case of form errors *** FAILED ***
[info]     java.lang.NullPointerException:
[info]     at views.html.helper.FieldElements$$anonfun$errors$2$$anonfun$apply$5.apply(Helpers.scala:35)
[info]     at views.html.helper.FieldElements$$anonfun$errors$2$$anonfun$apply$5.apply(Helpers.scala:35)
[info]     at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]     at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]     at scala.collection.immutable.List.foreach(List.scala:381)
[info]     at scala.collection.TraversableLike$class.map(TraversableLike.scala:234)
[info]     at scala.collection.immutable.List.map(List.scala:285)
[info]     at views.html.helper.FieldElements$$anonfun$errors$2.apply(Helpers.scala:35)
[info]     at views.html.helper.FieldElements$$anonfun$errors$2.apply(Helpers.scala:31)
[info]     at scala.Option.getOrElse(Option.scala:121)
[info]     ...
[info] ScalaTest
4

1 回答 1

0

在您发布的示例中,您尚未训练您的模拟。因此,当您尝试渲染模板时,它会尝试调用apply模拟并且它会抛出。供参考,MessagesApi

https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/i18n/Messages.scala#L320

正确训练这个模拟将非常困难。相反,您可以做的是构建一个实例DefaultMessagesApi并将其连接到您的控制器中:

val config = Configuration(ConfigFactory.load("application.conf")) // Or test.conf, if you have test-specific config files
val messages = new DefaultMessagesApi(Environment.simple(), config, new DefaultLangs(config))
val controller = wire[MyController]
于 2017-03-31T20:51:26.123 回答