Javaでテストするためのシステム時間のオーバーライド

1.概要

このクイックチュートリアルでは、テストのためにシステム時間を上書きする** さまざまな方法に焦点を当てます。

私たちのコードには現在の日付の前後に論理があることがあります。たぶん new Date() Calendar.getInstance() のようないくつかの関数呼び出しは、最終的には System.CurrentTimeMillis を呼び出します。

Java Clock の使用方法については、https://www.baeldung.com/java-clockを参照してください。または、AspectJを使用するには、https://www.baeldung.com/aspectj[here]を使用してください。

2. java.time でClockを使う

  • Java 8 java.time パッケージには、必要に応じて代替クロックを差し込むことを可能にする目的で、抽象クラス java.time.Clock ** が含まれています。それによって、私たちは自分の実装を差し込むことも、私たちのニーズを満たすためにすでに作られているものを見つけることもできます。

私たちの目標を達成するために、 上記のライブラリは特別な実装を生成するための静的メソッドを含んでいます 。そのうちの2つを使用して、不変、スレッドセーフ、および直列化可能な実装を返します。

最初のものは 固定 です。これから、 同じ Instant ** を返す Clock を得ることができます。これは、テストが現在のクロックに依存していないことを保証します。

それを使うには、 Instant ZoneOffset が必要です。

Instant.now(Clock.fixed(
  Instant.parse("2018-08-22T10:00:00Z"),
  ZoneOffset.UTC))
  • 2番目の静的メソッドは offset ** です。この例では、クロックが別のクロックをラップしているため、返されたオブジェクトは指定された期間だけ遅れるまたは早い瞬間を取得できます。

つまり、** 将来、過去、または任意の時点での実行をシミュレートすることができます。

Clock constantClock = Clock.fixed(ofEpochMilli(0), ZoneId.systemDefault());
//go to the future:
Clock clock = Clock.offset(constantClock, Duration.ofSeconds(10));
        //rewind back with a negative value:
clock = Clock.offset(constantClock, Duration.ofSeconds(-5));
 //the 0 duration returns to the same clock:
clock = Clock.offset(constClock, Duration.ZERO);

Duration クラスを使用すると、ナノ秒から数日まで操作することができます。また、期間を無効にすることもできます。つまり、長さを無効にしてこの期間のコピーを取得します。

3.アスペクト指向プログラミングを使う

システム時間をオーバーライドするもう1つの方法はAOPによるものです。このアプローチで、テストケース内で設定できる定義済みの値を返すために System クラスを作成することができます。

また、 System.currentTimeMillis() または new Date() への呼び出しを独自の別のユーティリティクラスにリダイレクトするために、アプリケーションクラスを織り込むことも可能です。

これを実装する1つの方法は、AspectJを使用することです。

public aspect ChangeCallsToCurrentTimeInMillisMethod {
    long around():
      call(public static native long java.lang.System.currentTimeMillis())
        && within(user.code.base.pckg.** ) {
          return 0;
      }
}

上の例では、 指定されたパッケージ内の System.currentTimeMillis ()へのすべての呼び出し(この場合は user.code.base.pckg。 )をキャッチし、このイベントが発生するたびにゼロを返します

ここで、ミリ秒単位で希望の時間を取得するための独自の実装を宣言できます。

AspectJを使用する利点の1つは、バイトコードレベルで直接動作するため、機能するために元のソースコードを必要としないことです。

そのため、再コンパイルする必要はありません。

4.まとめ

このクイック記事では、テストのためにシステム時間をオーバーライドするさまざまな方法について説明しました。最初は、ネイティブパッケージjava.timeとその Clock クラスを使い、最後に、 System クラスを織るためにアスペクトを適用します。

いつものように、コードサンプルはhttps://github.com/eugenp/tutorials/tree/master/core-java-8[GitHubに追加]を見つけることができます。