Почему объект java.util.Date удовлетворяет одному тесту Specs, но не проходит другой? - PullRequest
4 голосов
/ 03 апреля 2012

Я пытаюсь протестировать метод модели, используя Play Framework 2.0 и Specs2. Global.scala заполняет базу данных при первом запуске данными. В одном тесте я могу успешно протестировать его, используя следующий код:

def dateHelper(str: String): Date = new SimpleDateFormat("MM/dd/yyyy").parse(str)

"Food model" should {
  "be retrieved by id" in {
    val Some(mashedPotatoes) = Food.findById(1000)

    mashedPotatoes.name must equalTo("Mashed Potatoes")
    mashedPotatoes.eaten must equalTo(false)
    mashedPotatoes.id must equalTo(Id(1000))
    mashedPotatoes.owner must equalTo(Id(1))
    mashedPotatoes.expiry must equalTo(dateHelper("05/21/2012"))
  }
}

Этот тест пройден. Но если я попытаюсь выбрать более одного элемента из модели и протестировать его в виде списка:

"return food for test user in " in {

  running(FakeApplication()) {
    val testFoods: Seq[Food] = Food.findFoodFor(Id(1)) // Test user's ID is 1

// This test fails        
    testFoods must equalTo(
      List(
        Food(Id(1001), "Fried Green Tomatoes", false, Id(1), dateHelper("04/21/2012")),
        Food(Id(1000), "Mashed Potatoes", false, Id(1), dateHelper("05/21/2012"))
      )
    )

// This test passes
    testFoods.head.expiry must equalTo(dateHelper("04/21/2012"))
  }
}

Вывод ошибки говорит мне, что поля даты не равны:

[error] x return food for test user in
[error]     'Food(1001,Fried Green Tomatoes,false,1,2012-04-21 00:00:00.0), Food(1000,Mashed Potatoes,false,1,2012-05-21 00:00:00.0)' is not equal to 'Food(1001,Fried Green Tomatoes,false,1,Sat Apr 21 00:00:00 EDT 2012), Food(1000,Mashed Potatoes,false,1,Mon May 21 00:00:00 EDT 2012)' (ModelSpec.scala:66)
[error] Expected: ...se,1,[Sat Apr ]21...00[ EDT 2]0[12]),...1,[Mon May ]21...00[ EDT 2]0[12])
[error] Actual:   ...se,1,[2012-04-]21...00[.]0[]),...1,[2012-05-]21...00[.]0[])

Есть ли что-то, чего мне не хватает, здесь?

Редактировать: Похоже, что это была схема БД, в которой для столбца срока действия был задан тип timestamp, а не тип date.

Более полезная информация здесь: java.util.Date vs java.sql.Date

1 Ответ

3 голосов
/ 03 апреля 2012

Проблема, вероятно, из-за того, как данные загружаются из базы данных. Могу поспорить, что он использует java.sql.Timestamp вместо java.util.Date.

scala> val date = dateHelper("05/12/1974")
d: java.util.Date = Sun May 12 00:00:00 CDT 1974

scala> val dbDate = new java.sql.Timestamp(d.getTime)
dbDate: java.sql.Timestamp = 1974-05-12 00:00:00.0

scala> date == dbDate
res6: Boolean = true

scala> dbDate == date // prepare to be amazed!
res5: Boolean = false

Если вы прочитаете мелкий шрифт в Javadoc , вы найдете это милое маленькое утверждение:

Из-за различий между классом Timestamp и классом java.util.Date, упомянутых выше, рекомендуется, чтобы код не просматривал значения Timestamp в общем случае как экземпляр java.util.Date. Отношения наследования между меткой времени и java.util.Date действительно обозначают наследование реализации, а не наследование типов.

Возможно, что-то не так в вашем отображении ORM или в схеме базы данных. Является ли столбец DATE или TIMESTAMP или TIMESTAMP WITH TIMEZONE? Если это DATE, вы должны сопоставить это с java.sql.Date, что должно правильно сравниваться. Если это TIMESTAMP WITH TIMEZONE, тогда ваш dateHelper должен построить Timestamp с. Если это TIMESTAMP, удачи, так как база данных потеряет информацию о часовом поясе.

...