2016-04-27 19 views
1

測試處理表單的動作時遇到NullPointerException。有兩個操作,一個顯示,一個處理表單。測試第一個是好的;然而,測試第二個引發異常。這隻發生在單元測試中;該應用程序工作正常(即通過瀏覽器)。我無法弄清楚會發生什麼。任何人都可以幫我解釋一下嗎?我正在測試的代碼如下。單元測試處理表單的Play控制器的動作時引發NullPointerException

  • 斯卡拉:2.11.8
  • SBT:0.13.11
  • 遊戲框架:2.5.2

build.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 
) 

項目/插件.sbt

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

CONF /路由

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 
+0

你的帖子請求很可能是無效的 –

回答

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]