Play Framework with Internationalization测试失败

时间:2018-05-24 15:50:34

标签: scala playframework internationalization playframework-2.6 twirl

当我启用启用国际化的Play Scala 2.6应用程序时,将呈现该页面,其中所有内容都从我的messages.en文件中正确选取。

但是当我测试我的控制器时,其中一个测试在检查页面内容时失败了(contentAsString(result) must include ("Welcome to Play"))。

测试失败,因为页面内容呈现为label.welcome_to_play而不是Welcome to Play!。仅当我从控制器的新实例渲染索引页时才会发生这种情况。当我通过从应用程序或路由器渲染页面进行测试时,相同的测试(contentAsString)正在传递。

你知道为什么会这样吗?

这是我的HomeController.scala

@Singleton
class HomeController @Inject()(cc: ControllerComponents)
  extends AbstractController(cc) with I18nSupport {

  def index() = Action { implicit request: Request[AnyContent] =>
    Ok(views.html.index())
  }
}

这是我的HomeControllerSpec.scala测试:

class HomeControllerSpec extends PlaySpec
  with GuiceOneAppPerTest
  with Injecting
  with Results {

  "Calling HomeController.index" should {

    "render the index page from a new instance of controller" in {
      val controller = new HomeController(stubControllerComponents())
      val result = controller.index().apply(FakeRequest(GET, "/"))

      status(result) mustBe OK
      contentType(result) mustBe Some("text/html")
      // THIS IS WHERE THE TEST FAILS. Content appears as "label.welcome_to_play"
      contentAsString(result) must include ("Welcome to Play")
    }

    "render the index page from the application" in {
      val controller = inject[HomeController]
      val home = controller.index().apply(FakeRequest(GET, "/"))

      status(home) mustBe OK
      contentType(home) mustBe Some("text/html")
      // WHILE THIS IS PASSING
      contentAsString(home) must include ("Welcome to Play")
    }

    "render the index page from the router" in {
      val request = FakeRequest(GET, "/")
      val home = route(app, request).get

      status(home) mustBe OK
      contentType(home) mustBe Some("text/html")
      // AND THIS IS PASSING
      contentAsString(home) must include ("Welcome to Play")
    }
  }
}

这是我的index.scala.html观点:

@()(implicit messagesProvider: MessagesProvider)

@main(messagesProvider.messages("label.welcome_to_play")) {
  <h1>@messagesProvider.messages("label.welcome_to_play")</h1>
}

这是我的messages.en文件的样子:

label.welcome_to_play = Welcome to Play!

我的conf文件中有以下配置:

play.i18n {
  langs = [ "en" , "lv ]
}

我尝试将文件从messages.en重命名为messages,但没有帮助。

有谁知道测试失败的原因?为什么在从我的控制器的新实例渲染页面时没有使用消息文件?提前感谢您的帮助:)

2 个答案:

答案 0 :(得分:0)

MessagesApiControllerComponents提供,其中包含邮件列表及其翻译。

当您使用stubControllerComponentswill create MessagesApi个对象并带有no messages的对象时。

如果您需要翻译的消息,则需要使用其他ControllerComponents

答案 1 :(得分:0)

我最终以testMessages映射实例化DefaultMessagesApi,如下所示:

首先,我在testMessages内创建了一个HomeControllerSpec地图:

private val testMessages: Map[String, Map[String, String]] = Map(
  "en" -> Map(
    "label.welcome_to_play" -> "Welcome to Play!",
    "label.hello_world" -> "Hello world"
  )
)

此地图仅包含我要测试的标签的简短列表,而不是完整messages.en文件的副本。

然后在失败的测试中,我通过覆盖HomeController ...

来创建messagesApi的新实例。
"render the index page from a new instance of controller" in {
  val controller = new HomeController(stubControllerComponents()) {
    override val messagesApi = new DefaultMessagesApi(testMessages)
  }
  val result: Future[Result] = controller.index().apply(FakeRequest(GET, "/"))

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

...测试通过了。

我承认这种方法会造成一些重复(messages.en文件和规范内的消息标签),但是对于没有太多消息要测试的小型测试,我认为这是可以接受的解决方案。