System.currentTimeMillis()
いくつかのテスト目的で、何が返されるかを正確に予測したいと思います。System.currentTimeMillis()
が呼び出されたときに返されるものをフリーズまたは手動で設定する方法はありますか?
6 に答える
一般的なコードでSystem.currentTimeMillis
(など)を使用しないことを強くお勧めします。new Date()
代わりに、Clock
「現在の時刻を提供するサービス」を表すインターフェースを作成してから、何かを使用するSystem.currentTimeMillis
実装と、明示的に制御できる偽の実装を作成します。
依存性注入を使用して、このサービスのインスタンスを必要とするコードで利用できるようにします。実稼働ではSystem.currentTimeMillis
バージョンを使用し、テストでは偽物を使用します。
これにより、時間を停止するだけでなく、好きなように設定することができます。そのため、期限切れにならないことがわかっている静的なテスト データを使用したり、境界などのトリッキーなことを簡単にテストしたりできます。私はこれを使用しました。私の野田時間プロジェクトでは、それが「現在の時間」に到達する方法であるという点で、多くのプロジェクトで非常にうまくアプローチしています。
Java でかなりの時間作業を行っている場合は、Joda Timeを使用し、Clock
インターフェイスが次の値を返すようにすることをお勧めしInstant
ます。
public interface Clock {
Instant now();
}
はい、可能ですが、テスト コードの匂いです。
(このPowerMock の例のように) 静的メソッドをモックできるモック ライブラリを使用できますが、これを避け、他の回答が示唆するように時間データをカプセル化する必要があります。
PowerMockとMockitoを使用したテストは次のようになります。
@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
public class TestTime {
@Test
public void testTime() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(42l);
System.out.println(System.currentTimeMillis()); //prints 42
//your test code here
}
}
Java 8 に組み込まれた新しい java.time パッケージには、「必要に応じて代替クロックをプラグインできるようにするための java.time.Clock インターフェースが含まれています。代わりにこれを使用してください。
System.currentTimeMillis() をフリーズすることは可能ですか? いいえ
コードをテストできるようにする場合は、その時間値の周りに一種のラッパーを使用する必要があります
はい、解決策は存在します:
テスト目的で、独自のラッパーシステムを作成できます。たとえば、
package my.pack;
import java.io.PrintStream;
public class System
{
// reuse standard System.out:
public static PrintStream out = java.lang.System.out;
// do anything with chosen method
public static long currentTimeMillis()
{
return 1234567;
}
}
テストしたいクラスにインポートします
import my.pack.System;
その場合、System へのすべての呼び出しは独自の System クラスを介して渡されます。
ノート:
これは、「System.currentTimeMillis() を傍受する方法」の解決策です。
これは自動テストには適していません
これは「良いプログラムを設計する方法」の例ではありません。優れた設計を求める場合は、コードをリファクタリングし、 System.currentTimeMillis() を置き換える必要があります-他の回答を参照してください。