Help us understand the problem. What is going on with this article?

ScalaでLocalDateTime.nowを含むメソッドをテストする

概要

Scalaで現在時刻を取得するような処理を含むメソッドをテストする方法をいくつか考えてみました。
雑なTipsですm(_ _)m

現在時刻を取得する関数をデフォルト引数にする

こちらは現在時刻をデフォルト引数にする方法です。

// テスト対象のクラス
class DefaultArgTime {
  def getCurrentDayOfMonth(now: LocalDateTime = LocalDateTime.now()): Int =
    now.getDayOfMonth
}

// テストコード
class DefaultArgTimeSpec extends org.specs2.mutable.Specification {
  "#getCurrecntDayOfMonth" should {
    "return" in {
      new DefaultArgTime().getCurrentDayOfMonth(
        LocalDateTime.of(2020, 1, 1, 1, 1)
      ) === 1
    }
  }
}

テストコードでは単に現在時刻を引数として指定してやればいいだけなので、お手軽かと思います。個人的には一番よく使う方法です。
ただ、DefaultArgTimeの呼び出し元からは、自由にLocalDateTime型を渡せてしまうので、getCurrecntDayOfMonthは意図しない呼び出し方がされる危険性もあるかと思います。

テスト時に時刻を取得するメソッドをoverrideする

こちらは、現在時刻を取得する処理をprotectedメソッドで定義してやって、テスト時にoverrideするという方法です。

// テスト対象のクラス
class TraitTime {
  def getCurrentDayOfMonth(): Int = now.getDayOfMonth
  protected def now: LocalDateTime = LocalDateTime.now()
}

// テストコード
class TraitTimeSpec extends org.specs2.mutable.Specification {
  "#getCurrentDayOfMonth" should {
    "return" in {
      val traitTime = new TraitTime() {
        override protected def now: LocalDateTime =
          LocalDateTime.of(2020, 1, 1, 1, 1)
      }
      traitTime.getCurrentDayOfMonth() === 1
    }
  }
}

こちらの方法のメリットとしては、(先ほどの現在時刻をデフォルト引数として渡す方法と比較すると)publicメソッドの引数にnowのような余計な引数を定義する必要がないということが考えられます。
ただ、現在時刻を取得するprotectedメソッドを用意して、テスト時にoverrideするのは若干面倒ですね。

specs2-mockでspyする

こちらはspecs2-mockのspyメソッドを使った方法です。

// テスト対象のクラス
class SpyTime {
  def getCurrentDayOfMonth(): Int =
    now.getDayOfMonth

  def now: LocalDateTime = LocalDateTime.now()
}

// テストコード
class SpyTimeSpec extends Specification with Mockito {
  "#getCurrentDayOfMonth" should {
    "return" in {
      val spyTime = spy(new SpyTime())
      spyTime.now returns LocalDateTime.of(2020, 1, 1, 1, 1)
      spyTime.getCurrentDayOfMonth() === 1
    }
  }
}

nowを余計にpublicメソッドとして定義する必要があるので、無駄がありますが、場合によってはこの方法もアリかと思います。

microad
データとテクノロジーをかけ合わせたマーケティングプラットフォームを提供する会社です。
https://www.microad.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away