107

Joda Time には、時間をモック するための便利なDateTimeUtils.setCurrentMillisFixed()があります。

テストでは非常に実用的です。

Java 8 の java.time APIに相当するものはありますか?

4

12 に答える 12

82

最も近いものはClockオブジェクトです。任意の時間を使用して (またはシステムの現在の時間から) Clock オブジェクトを作成できます。すべての date.time オブジェクトnowには、現在の時刻の代わりに時計オブジェクトを受け取るメソッドがオーバーロードされています。したがって、依存性注入を使用して、Clock に特定の時刻を注入できます。

public class MyBean {
    private Clock clock;  // dependency inject
    ...
    public void process(LocalDate eventDate) {
      if (eventDate.isBefore(LocalDate.now(clock)) {
        ...
      }
    }
  }

詳細については、 Clock JavaDocを参照してください。

于 2014-06-30T13:57:19.577 に答える
27

新しいクラスを使用して、Clock.fixed作成を非​​表示にし、テストを簡素化しました。

public class TimeMachine {

    private static Clock clock = Clock.systemDefaultZone();
    private static ZoneId zoneId = ZoneId.systemDefault();

    public static LocalDateTime now() {
        return LocalDateTime.now(getClock());
    }

    public static void useFixedClockAt(LocalDateTime date){
        clock = Clock.fixed(date.atZone(zoneId).toInstant(), zoneId);
    }

    public static void useSystemDefaultZoneClock(){
        clock = Clock.systemDefaultZone();
    }

    private static Clock getClock() {
        return clock ;
    }
}
public class MyClass {

    public void doSomethingWithTime() {
        LocalDateTime now = TimeMachine.now();
        ...
    }
}
@Test
public void test() {
    LocalDateTime twoWeeksAgo = LocalDateTime.now().minusWeeks(2);

    MyClass myClass = new MyClass();

    TimeMachine.useFixedClockAt(twoWeeksAgo);
    myClass.doSomethingWithTime();

    TimeMachine.useSystemDefaultZoneClock();
    myClass.doSomethingWithTime();

    ...
}
于 2015-03-31T04:16:33.907 に答える
8

私はClockあなたの生産コードを乱雑に使用していることに気づきました。

JMockitまたはPowerMockを使用して、テスト コードで静的メソッド呼び出しをモックできます。JMockit の例:

@Test
public void testSth() {
  LocalDate today = LocalDate.of(2000, 6, 1);

  new Expectations(LocalDate.class) {{
      LocalDate.now(); result = today;
  }};

  Assert.assertEquals(LocalDate.now(), today);
}

編集:ここで同様の質問に対するJon Skeetの回答に関するコメントを読んだ後、私は過去の自分に同意しません。何よりも、この議論は、静的メソッドをモックするときにテストを並列化できないことを確信させました。

ただし、レガシーコードを処理する必要がある場合は、静的モックを使用できます/使用する必要があります。

于 2015-04-14T11:42:34.890 に答える
2

少し遅れましたがjava.date、Kotlin で API を使用して時間をモックするために使用するのは次のとおりです。

val now = LocalDate.of(2021, Month.FEBRUARY, 19)
val clock = Clock.fixed(Instant.ofEpochSecond(
    now.atStartOfDay().toEpochSecond(ZoneOffset.UTC)
), ZoneId.systemDefault())

次に、クロックをクラスに渡してテストできます

val classToTest = MyClass(clock)

もちろん、テスト可能なクラス内では、時計を使用して日付または時刻を取得します。

class MyClass(private val clock: Clock = Clock.systemDefaultZone()) {
    // ...
    fun doSomething() = LocalDate.now(clock)...
于 2021-02-19T18:43:07.957 に答える
1

java.time.Clockはmockito依存関係で使用しました

testImplementation("org.mockito:mockito-core")
testImplementation("org.mockito:mockito-inline")

サービス クラスはClock、テストでモックされるフィールドを使用します。

@Service
public class DeliveryWithDateService {
    private final Clock clock = Clock.systemUTC();

    public Delivery plan(UUID orderId) {
        return Delivery.builder()
                .id(UUID.randomUUID())
                .orderId(orderId)
                .createdAt(ZonedDateTime.now(clock))
                .plannedAt(ZonedDateTime.now(clock)
                        .plusDays(1)
                        .withHour(8)
                        .truncatedTo(ChronoUnit.HOURS))
                .build();
    }

    public Delivery ship(Delivery delivery) {
        return Delivery.builder()
                .id(delivery.getId())
                .orderId(delivery.getOrderId())
                .createdAt(delivery.getCreatedAt())
                .shippedAt(ZonedDateTime.now(clock))
                .build();
    }
}

@Value
@Builder
public class Delivery {
    private UUID id;
    private UUID orderId;
    private ZonedDateTime createdAt;
    private ZonedDateTime plannedAt;
    private ZonedDateTime shippedAt;
}

単体テストでは、 を使用してMockito.mockStaticをモックしClockます。

@SpringBootTest
public class DeliveryWithDateServiceTest {
    @Autowired
    private DeliveryWithDateService deliveryService;

    private static Clock clock;
    private static ZonedDateTime now;

    @BeforeAll
    static void setupClock() {
        clock = Clock.fixed(
                Instant.parse("2020-12-01T10:05:23.653Z"),
                ZoneId.of("Europe/Prague"));
        now = ZonedDateTime.now(clock);

        var clockMock = Mockito.mockStatic(Clock.class);
        clockMock.when(Clock::systemUTC).thenReturn(clock);
    }

    @Test
    void delivery_is_planned() {
        var orderId = UUID.randomUUID();
        var delivery = deliveryService.plan(orderId);

        var tomorrowAt8am = now.plusDays(1).withHour(8).truncatedTo(ChronoUnit.HOURS);

        assertAll(
                () -> assertThat(delivery).isNotNull(),
                () -> assertThat(delivery.getId()).isNotNull(),
                () -> assertThat(delivery.getOrderId()).isEqualTo(orderId),
                () -> assertThat(delivery.getCreatedAt()).isEqualTo(now),
                () -> assertThat(delivery.getPlannedAt()).isEqualTo(tomorrowAt8am),
                () -> assertThat(delivery.getShippedAt()).isNull()
        );
    }

    @Test
    void delivery_is_shipped() {
        var delivery = deliveryService.plan(UUID.randomUUID());
        var shipped = deliveryService.ship(delivery);
        assertAll(
                () -> assertThat(shipped).isNotNull(),
                () -> assertThat(shipped.getId()).isEqualTo(delivery.getId()),
                () -> assertThat(shipped.getOrderId()).isEqualTo(delivery.getOrderId()),
                () -> assertThat(shipped.getCreatedAt()).isEqualTo(delivery.getCreatedAt()),
                () -> assertThat(shipped.getShippedAt()).isEqualTo(now)
        );
    }
}
于 2021-09-11T11:21:45.583 に答える
0

jmockit を使用します。

コード:

// Mocking time as 9am
final String mockTime = "09:00:00"
new MockUp<LocalTime>() {
       @Mock
       public LocalTime now() {
           return LocalTime.parse(mockTime);
       }
};

輸入品:

import mockit.MockUp;
import mockit.Mock;

依存:

<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.41</version>
于 2021-06-25T06:55:46.133 に答える