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:
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 callingLocalDate.now()
method at many places in your code.Use
LocalDate.now(Clock)
method, that is pretty test-friendly, as already suggested in comments - again you've to modify your application code.Use
Powermockito
, if you can. In that case, you've a pretty easy approach by mocking static methods usingmockStatic(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
Calling Static Method from Another Java Class
Is Concurrenthashmap Totally Safe
How to Use Urlclassloader to Load a *.Class File
A Rotated Square Panel in Java Gui
Shuffle a List of Integers with Java 8 Streams API
Java 8 Default Methods as Traits:Safe
Java Equivalent of Unsigned Long Long
Best Language to Parse Extremely Large Excel 2007 Files
Numeric Textfield for Integers in Javafx 8 with Textformatter And/Or Unaryoperator
Mocking Time in Java 8's Java.Time API
Java: Rationale of the Cloneable Interface