Mock Java Date/Time for testing

Dmytro Stepanyshchenko
3 min readJan 20, 2021

--

In this article we will look at the problem of using the current time in the code and one of the solutions that I am fond of.

Using reference to the current date/time in the source code makes testing pretty difficult. You have to exclude such references from your assertions that sometimes is not a trivial task.

If we would like to avoid current time inconveniences during testing, time mocking is an answer. Here we will look at the example with mocking time using the new Java 8 Date/Time API (JSR 310).

For obtaining the current moment in time all related classes from java.time package have the static method now().

LocalDate.now();
LocalTime.now();
LocalDateTime.now();
OffsetDateTime.now();
ZonedDateTime.now();
Instant.now();

We will not consider the approach with mocking static methods due to its bad performance reputation.

If you look into the now() method of any Java API classes you will find that it is the overridden method that works with the system clock:

What we can do is creating the wrapper class with all necessary methods for the current time + an additional method for mocking time. For the sake of the demo, we will call it short and simple Time:

Let’s look into the wrapper class more closely:

  1. First of all, we remember the system clock and system timezone.
  2. Using method userMockTime() we can override time with the fixed clock and provided time zone.
  3. Using method useSystemDefaultZoneClock() we can reset the clock and timezone to the system defaults.
  4. All other methods use the provided clock instance.

So far so good. But there are 2 problems left in this approach:

  1. useMockTime() method is too dangerous for the production code. We would like somehow to eliminate the usage of that method in the source code.
  2. We need to enforce using Time class instead of the direct usage of the *Date/Time.now() methods.

One of the best solutions is ArchUnit library.

It gives you the opportunity to control your architectural rules using unit tests. Let’s see how we can define our rules using the JUnit 5 engine (also there is an option to define the same rules for the JUnit 4 engine).

We will need to add the necessary dependency (Maven example):

And add rule descriptions in the unit test folder:

As a bonus, we can also restrict usage of the old Date/Time API.

In case if you use an old library/framework that does not support a new Date/Time API we can create an adapter class for such purpose (please note that exclusion for the adapter class already defined in the previous rule):

As a final thing for the demo, we will create JUnit 5 extension that automatically mock time for a predefined value: for instance 01–04–2020 12:45 Europe/Kiev

Now let's imagine we have a simple method:

Then we can create a unit test:

The full source code of the example can be found here: Github repository

--

--

Responses (1)