如何解决测试scala中从LocalDate引起的副作用?

问题描述

我有一个函数,可以将以毫秒为单位的时间转换为LocalDate对象:

def convertToLocalDateTimeViaInstant(datetoConvert: java.util.Date): java.time.LocalDate =
    datetoConvert.toInstant.atZone(ZoneId.systemDefault).toLocalDate

我对此功能进行了单元测试,如下所示:

 "convertToLocalDateTimeViaInstant" should {
    "return the correct LocalDate instance" in new SAMLServiceTestEnv() {
      val timeInMillis: Long = 1349333576093L // Date is Thu Oct 04 2012 06:52:56 UTC in millis
      val someDate = new Date(timeInMillis) 
      val resultDate: LocalDate = samlServiceImpl.convertToLocalDateTimeViaInstant(someDate)
      
      resultDate.getYear mustEqual 2012
      resultDate.getMonth mustEqual java.time.Month.OCTOBER
      resultDate.getDayOfMonth mustEqual 4
    }
  }

当我单独运行此测试或整个文件时,此测试将做出正确的断言。值1349333576093L对应于Thu Oct 04 2012 06:52:56 UTC和Wed Oct 03 2012 23:52:56 PST(旧金山时间)。

但是,当我在项目中运行所有单元测试时,发现该测试失败。 resultDate.getDayOfMonth mustEqual 4断言未能说明4 is not equal to 3。我很惊讶地看到这一点,因为该函数在单独运行时清楚地考虑了UTC时间,但在一起运行时却以某种方式遵守本地时间?我在这里做什么错了?

解决方法

标准做法是不要直接使用LocalDate.now()。都一样您有一些ClockTimer正在为您提供当前时间,如果您需要在时间很重要的地方进行任何测试-您只需对当前时间提供者存根即可将时间固定为某个值。并且您完全从测试中删除了时间依赖性。设计可能会破坏其他任何方法,无论您希望如何“实用”。

事实上,Clock是JDK 8中的内置对象:https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html,因此您甚至不必引入新的依赖关系。