kagkarlsson / db-scheduler

Persistent cluster-friendly scheduler for Java
Apache License 2.0
1.23k stars 188 forks source link

Use Instant.now(clock) to Make Library Easier to Test #489

Open EarthCitizen opened 3 months ago

EarthCitizen commented 3 months ago

In order to have repeatable tests that avoid intermittent failures, it is necessary to control the system clock. When using methods such as Instant.now(), this hard-codes the library to using the system clock. There can be some static method mocking, but this is quite ugly and undesirable.

The best way to handle this is to use the Instant.now(clock) overloads instead. This would mean either providing a global mechanism to the library to provide a clock, or providing overloaded methods/contractors that take a clock.

I am aware of ManualScheduler (#399), but this is not so helpful in the case of Spring Boot. The ideal solution is to be able to provide an instance of java.time.Clock to the library.

A good example of this type of functionality is the AuditingEntityListener in Spring Boot that provides created at and updated at values when saving records to a DB. This functionality allows you to provide your own instance of DateTimeProvider. At runtime, you can just create a bean that uses system clock, and for tests you just override the bean and use a clock of your choosing. Then timestamps when saving are entirely under your control when testing.

Similarly, this library with Spring Boot could have a default bean that provides a clock, and this bean would not be created if the application provides one. Occurrences of Instant.now() would need to be replaced with Instant.now(clock).

In this case, there does not need to be a special scheduler. The default scheduler can be used accurately when testing.