Giriş
4 tane yöntem var. Bunlar şöyle
1. Wrap calls to the java.time API now() methods into a custom static class2. Use an injectable custom DateTime service.3. Inject a subclass of java.time.Clock.4. Intercept static calls to the now() methods with a mocking framework.
1. Static Wrapper yöntemi
Elimizde şöyle bir kod olsun. Bu kod test edebilmek içn setFixed() metodu sağlıyor. Bence çok iyi bir yöntem değil.
public class DateTimeWrapper { private static LocalDateTime instant; // For testing only public static void setFixed(Instant instant) { instant = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); } public static LocalDateTime currentDateTime() { if (instant != null) { return instant; } else { return LocalDateTime.now(); } } }
Bu kodun biraz daha gelişmiş hali şöyle
public class DateTimeWrapper { private static LocalDateTime instant; private static Duration offset; public static void setFixed(Instant instant) { DateTimeWrapper.instant = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); offset = null; } public static void setOffset(Duration duration) { offset = duration; instant = null; } public static LocalDateTime currentDateTime() { if (instant != null) { return instant; } else if (offset != null) { return LocalDateTime.now().plus(offset); } else { return LocalDateTime.now(); } } }
2: Custom Mutable DateTimeService Yöntemi
Örnek - Spring
Şöyle yaparız. Burada test için kendi LocalDateTime nesnemizi dönüyoruz.
public interface DateTimeService { LocalDateTime currentLocalDateTime(); } @Profile("!test") @Service public class DateTimeServiceImpl implements DateTimeService { @Override public LocalDateTime currentLocalDateTime(){ return LocalDateTime.now(); } } // The test implementation contains the same logic as the static wrapper @Profile("test") @Service public class MutableDateTimeService implements DateTimeService { @Override public LocalDateTime currentLocalDateTime() { //... } }
Testte şöyle yaparız
@SpringBootTest @Import(MutableDateTimeService.class) @ActiveProfiles("test") public class DateTimeServiceIntegrationTest { }
3: java.time.Clock Instance Kullanmak
Burada test için kendi Clock nesnemizi dönüyoruz.
Örnek - Spring
Elimizde şöyle bir kod olsun
@Autowired Clock clock; public ExecutionResult runBatchWithClock() { LocalDateTime started = LocalDateTime.now(clock); }
Şöyle yaparız
@Configuration public class TestConfig { @Bean Clock fixedClock(){ return Clock.fixed(Instant.from(someDateTime), ZoneId.systemDefault());} } }
Örnek
Test için elimizde şöyle bir kod olsun
@Slf4j @Configuration public class ClockConfig { @Value("${time-travel.instant:null}") private String timeTravelInstant; @Value("${time-travel.zone:null}") private String timeTravelZone; //@Bean //public Clock clock() { // return Clock.system(ZoneOffset.UTC); //} @Bean @ConditionalOnProperty(value = "time-travel.enabled", havingValue = "false", matchIfMissing = true) public Clock defaultClock() { log.info("Using system default zone clock"); return Clock.systemDefaultZone(); } //@Bean //public Clock clock() { // return Clock.fixed(Instant.parse("2022-09-01T12:00:00.00Z"), ZoneId.of("Europe/Warsaw")); //} @Bean @ConditionalOnProperty(value = "time-travel.enabled", havingValue = "true") public Clock clock() { log.info("Using fixed clock {} {}", timeTravelInstant, timeTravelZone); return Clock.fixed(Instant.parse(timeTravelInstant), ZoneId.of(timeTravelZone)); } }
Fixed clock için şöyle yaparız
time-travel.enabled=true time-travel.instant=2022-09-01T12:00:00.00Z time-travel.zone=UTC
4. Mockito Kullanmak
Şöyle yaparız. Bence en kolayı bu
@Test void runMockedDateTimeWithFixedTime() { try (MockedStatic<LocalDateTime> mockedStatic=Mockito.mockStatic(LocalDateTime.class)) { mockedStatic.when(() -> LocalDateTime.now(ArgumentMatchers.any(Clock.class))) .thenReturn(fixedLocalDateTime); var result = service.runBatchWithClock(); assertThat(result.started()).isEqualTo(result.finished()); } // notice that the static mocking is only in effect within the above try block, // which is of course how we would want it. assertThat(LocalDateTime.now() .getYear()) .isGreaterThanOrEqualTo(2022); }
Hiç yorum yok:
Yorum Gönder