8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MicroAd (マイクロアド)Advent Calendar 2020

Day 5

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

Last updated at Posted at 2020-12-04

概要

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メソッドとして定義する必要があるので、無駄がありますが、場合によってはこの方法もアリかと思います。

8
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?