How to Mock Java.Time.Localdate.Now()

How can I mock java.time.LocalDate.now()

In your code, replace LocalDate.now() with LocalDate.now(clock);.

You can then pass Clock.systemDefaultZone() for production and a fixed clock for testing.


This is an example :

First, inject the Clock. If you are using spring boot just do a :

@Bean
public Clock clock() {
return Clock.systemDefaultZone();
}

Second, call LocalDate.now(clock) in your code :

@Component
public class SomeClass{

@Autowired
private Clock clock;

public LocalDate someMethod(){
return LocalDate.now(clock);
}
}

Now, inside your unit test class :

// Some fixed date to make your tests
private final static LocalDate LOCAL_DATE = LocalDate.of(1989, 01, 13);

// mock your tested class
@InjectMocks
private SomeClass someClass;

//Mock your clock bean
@Mock
private Clock clock;

//field that will contain the fixed clock
private Clock fixedClock;

@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);

//tell your tests to return the specified LOCAL_DATE when calling LocalDate.now(clock)
fixedClock = Clock.fixed(LOCAL_DATE.atStartOfDay(ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault());
doReturn(fixedClock.instant()).when(clock).instant();
doReturn(fixedClock.getZone()).when(clock).getZone();
}

@Test
public void testSomeMethod(){
// call the method to test
LocalDate returnedLocalDate = someClass.someMethod();

//assert
assertEquals(LOCAL_DATE, returnedLocalDate);
}

How to mock LocalDateTime.now() in java 8

You should use Mockito#mockStatic for this use case.

You can use it like this

try(MockedStatic<LocalDateTime> mock = Mockito.mockStatic(LocalDateTime.class, Mockito.CALLS_REAL_METHODS)) {
doReturn(LocalDateTime.of(2030,01,01,22,22,22)).when(mock).now();
// Put the execution of the test inside of the try, otherwise it won't work
}

Notice the usage of Mockito.CALLS_REAL_METHODS which will guarantee that whenever LocalDateTime is invoked with another method, it will execute the real method of the class.

How can I fake the date returned by java.time.LocalDate?

There are a few options you've:

  1. Wrap the LocalDate.now() call in a non-static method of a class. Then you can mock that method to return your specific instance - This would not seem practical if you're directly calling LocalDate.now() method at many places in your code.

  2. Use LocalDate.now(Clock) method, that is pretty test-friendly, as already suggested in comments - again you've to modify your application code.

  3. Use Powermockito, if you can. In that case, you've a pretty easy approach by mocking static methods using mockStatic(Class<?>) method.

The 3rd approach can be implemented as:

@PrepareForTest({ LocalDate.class })
@RunWith(PowerMockRunner.class)
public class DateTest {
@Test
public void yourTest() {
PowerMockito.mockStatic(LocalDate.class);
when(LocalDate.now()).thenReturn(yourLocalDateObj);
}
}

Mocking LocalDate.now() but when using plusDays it returns null?

java.time.Clock

Instead of mocking a static method (which is never a good idea really IMO) you can use the Clock feature offered by the java.time API itself. You can pass an instance of java.time.Clock, a fixed clock for example.

From the Clock JavaDoc:

Best practice for applications is to pass a Clock into any method that requires the current instant. A dependency injection framework is one way to achieve this:

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

This approach allows an alternate clock, such as fixed or offset to be used during testing.

How to mock the minute value when mocking LocalDateTime?

Converting to LocalDate will remove the time part of your LocalDateTime, so don't do that.

Initialize your fixedClock like this:

fixedClock = Clock.fixed(
LOCAL_DATE_TIME.atZone(ZoneId.systemDefault()).toInstant(),
ZoneId.systemDefault()
);

How to mock LocalDatTime.now() using mockito?

My suggestion is that you inject a dependency on a Clock and use that in your method. Apologies that I've converted to Java as I'm not too familiar with kotlin.

class ClassToTest {
private final Clock;

public ClassToTest(Clock clock) {
this.clock = clock;
}

private boolean isExpired(Access access) {
return access.validUntil.isAfter(LocalDateTime.now(clock));
}
}

And the test that uses a fixed 'now' would look like:

@Test
void testIsExpired() {
Clock clock = mock(Clock.class);
when(clock.instant()).thenReturn(Instant.ofEpochSecond(1000L));
when(clock.getZone()).thenReturn(ZoneOffset.UTC);
ClassToTest test = new ClassToTest(clock);
assertThat(test.isExpired(access))...
}

You specifically asked about mocking but you could achieve the same with a constant clock:

@Test
void testIsExpired() {
Clock clock = Clock.fixed(Instant.ofEpochSecond(1000L), ZoneOffset.UTC);
ClassToTest test = new ClassToTest(clock);
assertThat(test.isExpired(access))...
}

Your production code would inject whichever clock you want (such as a particular TZ, local TZ, clocks that tick each second etc.) which are all created using static Clock methods. The ability to change clocks is often a useful feature to have on top of its value for testing.

Mocking time in Java 8's java.time API

The closest thing is the Clock object. You can create a Clock object using any time you want (or from the System current time). All date.time objects have overloaded now methods that take a clock object instead for the current time. So you can use dependency injection to inject a Clock with a specific time:

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

See Clock JavaDoc for more details



Related Topics



Leave a reply



Submit