If you need to freeze time for a Spring Boot integration test, the easiest option is to define a custom bean for Clock object for test profile. Eg

@TestConfiguration
class ClockTestConfiguration {

    @Bean
    @Primary
    Clock clock() {
        return mock(Clock.class);
    }
}

This only works if the Clock object is injected by Spring into a component (Controller/Service/Repository etc.,)

What if you have a Clock object in your DTO class like below?

public class TimeDTO {

    public final Clock clock = Clock.systemUTC();

    private Instant getNow() {
        return Instant.now(clock);
    }

}

If you want to write deterministic tests for getNow method, you can use ReflectionTestUtils and Clock.fixed.

@Test
void testNow() {
    ZoneId zone = ZoneId.systemDefault();
    TimeDTO time = new TimeDTO();
    ReflectionTestUtils.setField(time, "clock", Clock.fixed(Instant.parse("2021-05-18T10:00:00Z"), zone));

        assertEquals("2021-05-18T20:00:00+10:00[Australia/Sydney]",
                time.getNow().atZone(zone).format(DateTimeFormatter.ISO_DATE_TIME));
    }

This will override the value of clock field in the time object.

Leave a Reply

Your email address will not be published. Required fields are marked *